Skip to content

feat(security): add DE0708 no-non-FIPS-hasher lint; replace all direct sha2 usage with FNV-1a#4080

Merged
Artifizer merged 1 commit into
constructorfabric:mainfrom
mattgarmon:fips
Jun 12, 2026
Merged

feat(security): add DE0708 no-non-FIPS-hasher lint; replace all direct sha2 usage with FNV-1a#4080
Artifizer merged 1 commit into
constructorfabric:mainfrom
mattgarmon:fips

Conversation

@mattgarmon

@mattgarmon mattgarmon commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Closes #3415

  • Add dylint lint DE0708 (no_non_fips_hasher) rejecting sha2/sha1/md5 imports; allow-list is empty - all direct usage eliminated
  • Replace sha2::Sha256 in toolkit-odata pagination with inline FNV-1a (non-cryptographic cursor fingerprint)
  • Replace sha2::Sha256 in oidc-authn-plugin credential_fingerprint with inline FNV-1a (cache-busting key)
  • Remove sha2 and hex dependencies from toolkit-odata and oidc-authn-plugin
  • Add sha2 as Phase B candidate in deny-fips.toml (Phase A blocked by transitive deps: sqlx-core, sqlx-postgres, lopdf, rust-embed-utils)
  • Document in SECURITY.md §7 and §9

Summary by CodeRabbit

  • New Features

    • Added DE0708 security lint to block new imports of non‑FIPS hashers.
  • Documentation

    • Expanded security docs with FIPS crypto policy and the DE0708 guidance.
    • Noted Phase B deny-list candidate entry for non‑FIPS hasher paths.
  • Chores

    • Replaced cryptographic digests with deterministic FNV‑1a fingerprints for caching and short IDs.
    • Cleaned up related dependency declarations.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Replaces direct SHA-2 usage with deterministic 64-bit FNV-1a in OIDC token caching and OData pagination, marks sha2 as a Phase B candidate in deny-fips.toml, adds SECURITY.md notes, and introduces DE0708 dylint with UI tests plus allow-list plumbing.

Changes

SHA-256 Elimination and DE0708 Lint Enforcement

Layer / File(s) Summary
FIPS Policy and Security Documentation
deny-fips.toml, docs/security/SECURITY.md
Added a commented Phase B candidate entry for sha2 and documented DE0708 and the "Non‑FIPS hasher guard" in SECURITY.md.
OIDC Plugin: SHA-256 to FNV-1a Migration
gears/system/authn-resolver/plugins/oidc-authn-plugin/Cargo.toml, gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client.rs
Removed sha2/hex workspace deps from the crate, removed the sha2 import, implemented an internal 64-bit FNV-1a credential_fingerprint, and changed cache key label to secret_fnv1a.
OData Toolkit: SHA-256 to FNV-1a Migration
libs/toolkit-odata/Cargo.toml, libs/toolkit-odata/src/pagination.rs
Removed sha2/hex deps, deleted SHA-256 import, added fnv1a_64 helper, and rewired short_filter_hash to return a 16-character lowercase hex FNV-1a digest.
DE0708 Lint: Core Implementation
tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/src/lib.rs
Added DE0708_NO_NON_FIPS_HASHER early lint detecting use imports of sha2,sha1,md5, resolving grouped imports, skipping allow-listed spans, and emitting diagnostics with help and docs note; includes tests.
DE0708 Lint: UI Test Examples
tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.rs, tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.stderr, tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/good_allowed_path.rs
Added UI fixtures: a failing sha2 import example, its expected stderr, and a non-triggering allowed-path example.
DE0708 Lint: Workspace Setup and Allow-List
tools/dylint_lints/Cargo.toml, tools/dylint_lints/README.md, tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/Cargo.toml, tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md, tools/dylint_lints/lint_utils/src/lib.rs
Registered the new lint crate in workspace members, added sha2 to workspace.dependencies for dev/test, added lint docs, and introduced is_in_hasher_allow_list() placeholder in lint_utils.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I swapped the hashes, made the cache light,
FNV hums softly through pagination's night,
A lint stands watch with DE0708 in sight,
Sha2 sits waiting, commented out but polite,
Hooray, small hops toward a safer byte!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main changes: adding the DE0708 no-non-FIPS-hasher lint and replacing direct sha2 usage with FNV-1a, which aligns with the changeset's primary objectives.
Linked Issues check ✅ Passed All three acceptance criteria from issue #3415 are met: SECURITY.md §9 documents the non-crypto usage, DE0708 lint rejects sha2/sha1/md5 imports outside an allow-list, and all direct sha2 call sites have been replaced with FNV-1a.
Out of Scope Changes check ✅ Passed All changes directly support issue #3415 requirements: the lint implementation, documentation updates, sha2 replacement with FNV-1a, dependency removals, and deny-fips.toml Phase B entry are all within scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@mattgarmon
mattgarmon force-pushed the fips branch 2 times, most recently from de313ff to a47f32d Compare June 11, 2026 23:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md (1)

1-27: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a Table of Contents to this artifact README.

Line 1 starts a multi-section doc, but there is no TOC section.

📚 Proposed update
 # DE0708: No Non-FIPS Hasher Imports
 
+## Table of Contents
+
+- [Why](`#why`)
+- [Allow-list](`#allow-list`)
+- [Example](`#example`)
+- [References](`#references`)
+
 Prohibits imports of non-FIPS-validated hash crates (`sha2`, `sha1`, `md5`) outside an explicit allow-list.

As per coding guidelines, **/*.{md,markdown,adoc,asciidoc}: Generate Table of Contents (TOC) for artifact documentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md` around
lines 1 - 27, Add a Table of Contents section to the DE0708 README by inserting
a "## Table of Contents" block after the title and listing the existing
top-level sections (Why, Allow-list, Example, References) as links; update the
README.md near the top so readers can jump to sections and ensure the TOC
reflects the file’s headings and stays in sync with future edits (no code
changes to is_in_hasher_allow_list() are required, but mention of that function
can remain in the Allow-list section).

Source: Coding guidelines

🧹 Nitpick comments (2)
gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client.rs (1)

227-233: ⚡ Quick win

Consider extracting fnv1a_64 to a shared utility module.

The identical fnv1a_64 implementation is duplicated here and in libs/toolkit-odata/src/pagination.rs. Extracting it to a common crate (e.g., lint_utils or a new hash_utils module) would eliminate duplication and ensure consistent behavior if the algorithm ever needs adjustment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client.rs`
around lines 227 - 233, The fnv1a_64 hash implementation is duplicated; extract
it to a shared utility (e.g., new crate or common module like hash_utils) as a
single pub fn fnv1a_64(data: &[u8]) -> u64, move the implementation out of
token_client.rs and pagination.rs, update both call sites to import the new
module (use crate::hash_utils::fnv1a_64 or use hash_utils::fnv1a_64 depending on
crate layout), remove the duplicated versions, run cargo build and tests, and
ensure build_cache_key (and any callers) use the centralized fnv1a_64 so
behavior remains identical across the codebase.
tools/dylint_lints/README.md (1)

44-47: ⚡ Quick win

Add a TOC for this README.

The markdown docs guideline calls for a table of contents, and this file is now long enough that navigation would benefit from one.

As per coding guidelines, **/*.{md,markdown,adoc,asciidoc}: Generate Table of Contents (TOC) for artifact documentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/dylint_lints/README.md` around lines 44 - 47, Add a Table of Contents
near the top of tools/dylint_lints/README.md (directly after the main
title/header) that lists and links to the major sections (e.g., Security
(DE07xx) and other primary headings present in the file) so readers can jump to
subsections; ensure the TOC follows the repo markdown-docs guideline for
generating TOCs for **/*.{md,markdown,adoc,asciidoc} by including internal
markdown anchor links for each header in the README so navigation and automated
TOC tooling will work.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/security/SECURITY.md`:
- Around line 448-449: The AuthN Resolver documentation still mentions using
"sha256(token)" for the OIDC cache key, which conflicts with the new FNV-1a
usage; update that earlier sentence to match the change in
oidc-authn-plugin/src/infra/token_client.rs and
libs/toolkit-odata/src/pagination.rs by replacing the "sha256(token)" wording
with a description that the cache key uses an inline FNV-1a non-cryptographic
fingerprint (or equivalent phrasing referencing the FNV-1a implementation used)
so both sections consistently describe the same cache-key fingerprint.

In `@libs/toolkit-odata/src/pagination.rs`:
- Around line 82-101: Cursor hash format is not versioned so old cursors can
fail FilterMismatch when short_filter_hash
(toolkit_odata::pagination::short_filter_hash) or normalize_filter_for_hash
changes; update cursor encoding and validation to include a hash-algorithm
identifier and accept legacy formats during a transition. Specifically: change
CursorV1.f to store a prefixed string like "fnv1a:<hex>" (or add a separate
enum/field for algorithm) and update validate_cursor_against to parse and
compare algorithm-prefixed hashes, falling back to the legacy raw hex comparison
for backward compatibility; ensure effective_filter_hash generation in
short_filter_hash emits the same prefix and add acceptance logic for both
prefixed and unprefixed legacy values to avoid immediate FilterMismatch failures
during rollout.

---

Outside diff comments:
In `@tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md`:
- Around line 1-27: Add a Table of Contents section to the DE0708 README by
inserting a "## Table of Contents" block after the title and listing the
existing top-level sections (Why, Allow-list, Example, References) as links;
update the README.md near the top so readers can jump to sections and ensure the
TOC reflects the file’s headings and stays in sync with future edits (no code
changes to is_in_hasher_allow_list() are required, but mention of that function
can remain in the Allow-list section).

---

Nitpick comments:
In
`@gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client.rs`:
- Around line 227-233: The fnv1a_64 hash implementation is duplicated; extract
it to a shared utility (e.g., new crate or common module like hash_utils) as a
single pub fn fnv1a_64(data: &[u8]) -> u64, move the implementation out of
token_client.rs and pagination.rs, update both call sites to import the new
module (use crate::hash_utils::fnv1a_64 or use hash_utils::fnv1a_64 depending on
crate layout), remove the duplicated versions, run cargo build and tests, and
ensure build_cache_key (and any callers) use the centralized fnv1a_64 so
behavior remains identical across the codebase.

In `@tools/dylint_lints/README.md`:
- Around line 44-47: Add a Table of Contents near the top of
tools/dylint_lints/README.md (directly after the main title/header) that lists
and links to the major sections (e.g., Security (DE07xx) and other primary
headings present in the file) so readers can jump to subsections; ensure the TOC
follows the repo markdown-docs guideline for generating TOCs for
**/*.{md,markdown,adoc,asciidoc} by including internal markdown anchor links for
each header in the README so navigation and automated TOC tooling will work.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 93184dd7-1caf-40a1-9626-e49db250d448

📥 Commits

Reviewing files that changed from the base of the PR and between e3ab3c2 and a47f32d.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • tools/dylint_lints/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • deny-fips.toml
  • docs/security/SECURITY.md
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/Cargo.toml
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client.rs
  • libs/toolkit-odata/Cargo.toml
  • libs/toolkit-odata/src/pagination.rs
  • tools/dylint_lints/Cargo.toml
  • tools/dylint_lints/README.md
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/Cargo.toml
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/src/lib.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.stderr
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/good_allowed_path.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/good_allowed_path.stderr
  • tools/dylint_lints/lint_utils/src/lib.rs
💤 Files with no reviewable changes (2)
  • libs/toolkit-odata/Cargo.toml
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/Cargo.toml

Comment thread docs/security/SECURITY.md
Comment thread libs/toolkit-odata/src/pagination.rs
…t sha2 usage with FNV-1a

Signed-off-by: mattgarmon <mjg2790@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md (1)

1-27: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a TOC to this README.

This artifact doc is missing the required Table of Contents section, so navigation is less consistent with the repo’s documentation standard. As per coding guidelines, **/*.{md,markdown,adoc,asciidoc}: Generate Table of Contents (TOC) for artifact documentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md` around
lines 1 - 27, The README for DE0708 lacks a Table of Contents; add a TOC near
the top of tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md
listing the major headings (Why, Allow-list, Example, References) with anchor
links to each section so the document matches repo artifact-doc standards;
ensure the TOC appears before the first section and update any section headings
if needed so anchors are correct, and mention in the TOC the note about
is_in_hasher_allow_list() in lint_utils/src/lib.rs as the locus for allow-list
changes.

Source: Coding guidelines

🧹 Nitpick comments (1)
libs/toolkit-odata/src/pagination.rs (1)

83-100: ⚡ Quick win

Add a golden hash regression test.

Line 83 changes the serialized filter_hash algorithm/format, but the current tests only prove self-consistency and output length. A future tweak to the FNV constants, hex casing, or normalized byte stream would still pass while silently changing the cursor contract consumed by validate_cursor_against.

Please pin one representative expression to an exact 16-character hash value in the test suite.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/toolkit-odata/src/pagination.rs` around lines 83 - 100, Tests only check
self-consistency of the filter hash but not a pinned output; add a golden
regression test that computes the hash for one representative expression using
normalize_filter_for_hash and fnv1a_64 (formatted with "{:016x}") and asserts it
equals a fixed 16-character hex string; place the test alongside existing
pagination tests (or in the same test module that covers
validate_cursor_against) so any future accidental changes to fnv1a_64, hex
formatting, or normalization will fail until intentionally updated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md`:
- Around line 1-27: The README for DE0708 lacks a Table of Contents; add a TOC
near the top of
tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md listing the
major headings (Why, Allow-list, Example, References) with anchor links to each
section so the document matches repo artifact-doc standards; ensure the TOC
appears before the first section and update any section headings if needed so
anchors are correct, and mention in the TOC the note about
is_in_hasher_allow_list() in lint_utils/src/lib.rs as the locus for allow-list
changes.

---

Nitpick comments:
In `@libs/toolkit-odata/src/pagination.rs`:
- Around line 83-100: Tests only check self-consistency of the filter hash but
not a pinned output; add a golden regression test that computes the hash for one
representative expression using normalize_filter_for_hash and fnv1a_64
(formatted with "{:016x}") and asserts it equals a fixed 16-character hex
string; place the test alongside existing pagination tests (or in the same test
module that covers validate_cursor_against) so any future accidental changes to
fnv1a_64, hex formatting, or normalization will fail until intentionally
updated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c15fcdf5-5df8-4575-a90c-405cb2df39e7

📥 Commits

Reviewing files that changed from the base of the PR and between a47f32d and db4df35.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • tools/dylint_lints/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • deny-fips.toml
  • docs/security/SECURITY.md
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/Cargo.toml
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client.rs
  • libs/toolkit-odata/Cargo.toml
  • libs/toolkit-odata/src/pagination.rs
  • tools/dylint_lints/Cargo.toml
  • tools/dylint_lints/README.md
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/Cargo.toml
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/README.md
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/src/lib.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.stderr
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/good_allowed_path.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/good_allowed_path.stderr
  • tools/dylint_lints/lint_utils/src/lib.rs
💤 Files with no reviewable changes (2)
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/Cargo.toml
  • libs/toolkit-odata/Cargo.toml
✅ Files skipped from review due to trivial changes (2)
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/Cargo.toml
  • tools/dylint_lints/README.md
🚧 Files skipped from review as they are similar to previous changes (8)
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.stderr
  • tools/dylint_lints/lint_utils/src/lib.rs
  • deny-fips.toml
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/bad_sha2_import.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/ui/good_allowed_path.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/src/lib.rs
  • docs/security/SECURITY.md
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client.rs

@Artifizer
Artifizer merged commit ff46fa0 into constructorfabric:main Jun 12, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIPS] modkit-odata: Document sha2 pagination hash as non-crypto and add dylint guard

3 participants