Skip to content

test+hardening: pin the untested defenses, cap what limits couldn't, heal the fuzzers - #80

Merged
systemslibrarian merged 3 commits into
mainfrom
assurance/tests-vectors-hardening
Sep 5, 2026
Merged

systemslibrarian merged 3 commits into
mainfrom
assurance/tests-vectors-hardening

Conversation

@systemslibrarian

Copy link
Copy Markdown
Owner

Replaces #78 (auto-closed when its stacked base branch was deleted on merge of #77 — same branch, same single commit, full description and verification record in #78).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sym7RJ7ehNhbMXytE5rMmS

systemslibrarian and others added 3 commits September 4, 2026 06:35
…ps it that way

Merged follow-through from two independent reviews (the multi-agent security
audit and an external product review), scoped strictly inside the 1.x format
freeze: docs, metadata, and one XML-docs addition. No byte meaning, reader
acceptance, or API change.

Resurrect the docs-consistency guard:
- .github/workflows/docs-consistency.yml now exists — the workflow the 1.7.0
  changelog advertised but never shipped. It runs check-docs-consistency.sh on
  every push and PR.
- The script is portable (no GNU-only grep -P, so it runs on macOS) and now
  also checks the SECURITY.md supported-versions cell, the ROADMAP-2.0 "Today"
  cell, the AUDIT-SCOPE pinned tag, artifact-name examples, release-download /
  reproducibility / clone-at-tag commands, and install snippets in all Markdown
  (CHANGELOG excluded as history). Verified green on this tree and on macOS.

Version sweep to 1.7.1 (was scattered across 1.0.1–1.7.0): SECURITY.md table,
ROADMAP "Now" heading, KNOWN-GAPS + GOLD-STANDARD review markers, ROADMAP-2.0
Today cell, AUDIT-SCOPE pinned tag (v1.7.1 / e0d332a), README + SUPPLY-CHAIN +
REPRODUCIBLE-BUILDS worked examples, ANNOUNCE snippets, CHANGELOG compare-link
footer (adds 1.7.0/1.7.1). PackageValidationBaselineVersion 1.5.0 → 1.7.1
(pack verified against the published baseline). PackageReleaseNotes reworded
version-agnostic so they cannot silently go stale on nuget.org.

Recalibrate claims to what the code does and tests pin:
- SECURITY.md: no-oracle bullet now states the true property (one exception
  type; byte-identical messages for key-dependent failures; structural
  diagnostics are key-independent); integrity scoped to the authenticated
  envelope (trailing bytes after the final frame are ignored — KNOWN-GAPS);
  bounded-work notes tight ceilings are opt-in via PqDecryptionLimits.Untrusted;
  Dependencies now names Signing's BouncyCastle use and the Rust demo core's
  pre-1.0 RustCrypto crates; SBOM list covers all eight per-package SBOMs.
- SUPPLY-CHAIN.md: artifact table lists all nine packages; snupkg files are
  documented as NOT attested (verifying one fails by construction); the
  reproducibility script's 4-of-9 package coverage is stated; "every push"
  heading acknowledges scheduled jobs.
- GOLD-STANDARD.md: binary-compat row downgraded to ⚠️ — validation is
  overridden off in Aws/AzureKeyVault/Gcp/Analyzers (stale pre-first-publish
  gate); PublicAPI baseline count corrected to seven packages.

Correct the rotation story (KEY-MANAGEMENT.md): header-only CEK rewrap cannot
ship on format v2 — the header is AAD for every frame, so a rewrap re-tags
every chunk, and doing so under the same CEK and nonces with new AAD emits
second GCM tags for existing (key, nonce) pairs while old copies coexist,
making the GCM authentication key recoverable. Rotation is now documented as a
streaming transcode (fresh CEK + nonce prefix, full-file I/O, detached
signatures invalidated); true header-only rewrap is banked as a format-v3
candidate. Status list also gains the shipped Gcp provider and multi-recipient
moves to past tense.

Format-doc errata (doc-only, matching the frozen implementation):
- KEY-FILE-FORMAT.md: a PQKF body is a KeySource-1 passphrase container whose
  KeyParams carry KdfId 1 (PBKDF2) or 2 (Argon2id) — previous text conflated
  KeySource with KdfId and would misdirect an independent implementer.
- FILE-FORMAT.md: KeySource-2 HKDF formulas now state salt = absent.

KNOWN-GAPS.md gains five verified entries: header-only rewrap (v3 candidate),
IContentKeyProvider key-freshness contract and its GCM consequences, passphrase
Unicode normalization, non-interruptible KDF derivation, and default
permissions on decrypted output. IContentKeyProvider.WrapNewKeyAsync's XML docs
now state why the fresh-key contract is load-bearing (build clean, 0 warnings).

CLAUDE.md's version-bump checklist now names every reference class that
drifted, so the next release sweep is complete by construction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sym7RJ7ehNhbMXytE5rMmS
…heal the fuzzers

The assurance batch from the merged review follow-through (multi-agent audit +
two external reviews), all inside the 1.x format freeze — no byte meaning or
reader acceptance changes; the corpus grows, nothing in it changes.

Conformance corpus (+9 vectors, both implementations green):
- Deterministic two-chunk positive pos-passphrase-pbkdf2-multichunk.
- Argon2id bounds negatives (memory/iterations/parallelism/salt): the Rust
  reader's cost checks previously had zero test coverage anywhere.
- Framing negatives: clean-boundary truncation (first exercise of the Rust
  saw_final path), frame swap (first Rust ordinal-binding coverage), dropped
  final frame, and a cross-container frame transplant backing SECURITY.md's
  "splicing between containers" claim with committed bytes.
- The generator now reuses the pinned hybrid lenient vector instead of
  re-randomizing it on regen, and regeneration reproduces the corpus
  bit-for-bit (verified: regen produced only additions).

Limits: PqDecryptionLimits.MaxArgon2Parallelism (default 255 = format maximum,
so acceptance is unchanged; Untrusted caps at 8), enforced pre-derivation
beside the memory/iteration ceilings. A hostile header could previously demand
255 Argon2 lanes and no limit could say no.

Key-file hardening: PqKeyFileFormat.Decrypt output is a fixed-capacity buffer
sized to the expected key rather than the whole file — kills the
attacker-proportional allocation and the wrong-type reallocation that escaped
the zeroing finally. Same exceptions, same messages.

Fuzz health: both .NET targets now run under Untrusted limits (format-legal
2 GiB-KDF headers stalled single iterations ~20 min and failed 13/30 recent
scheduled runs), plus -timeout=20 and timeout-*/oom-* artifact upload in CI.

Tests: ZeroizationTests (engine success/failure/cancellation + Dispose paths —
a documented defense with previously zero coverage that has regressed before),
cross-container transplant, KeySource-4 block swap/strip/duplicate,
SHA256SUMS integrity (was verified by nothing), Argon2 parallelism limits.
Suite: 636 passing across net8.0+net10.0; cargo conformance suite green.

Hygiene: analyzer rules PQFE101-104 moved to the shipped ledger (1.5.0);
System.Formats.Asn1 transitive floored at 8.0.1 in the analyzer test project
(CVE-2024-38095, test-only).

Docs made true: SECURITY.md discloses the stage-distinguishable error caveat
(key-unwrap vs body-auth — recorded in KNOWN-GAPS with the unification decision
explicitly open); CONFORMANCE.md §3 names the corpus vector for each MUST;
REPRODUCIBLE-BUILDS.md retracts the cross-OS claim — a macOS arm64 rebuild of
v1.7.1 differs from the published package (reproduced locally with the repo's
own verifier; Linux CI remains the demonstrated envelope); README says
"provenance-attested releases" (there is no author/tag signing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sym7RJ7ehNhbMXytE5rMmS
@systemslibrarian
systemslibrarian merged commit 72548b8 into main Sep 5, 2026
10 checks passed
@systemslibrarian
systemslibrarian deleted the assurance/tests-vectors-hardening branch September 5, 2026 00:14
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.

1 participant