Skip to content

Fix the findings of the pre-release review - #1

Merged
yi-here merged 2 commits into
mainfrom
claude/nice-hawking-5hmp9x
Sep 24, 2026
Merged

yi-here merged 2 commits into
mainfrom
claude/nice-hawking-5hmp9x

Conversation

@yi-here

@yi-here yi-here commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Fixes everything found by an internal, AI-assisted pre-release review. Three separate AI reviewers each worked from a frozen snapshot, covering the cryptographic construction, the implementation and the public claims. A fourth re-tested the fixes. This is not an independent audit by human cryptographers, and CHANGELOG.md says so.

Every code fix comes with a test that failed before it.

Findings fixed

Severity Finding Fix
High The documented AuthKey cutover chose the envelope per row from schema_version, a column the forger writes, so following the docs re-opened forgery New Reseal; cutover is now: re-seal once, then read authenticated only. The forgery window (until the migration finishes) is documented. A test pins the old advice as unsafe.
Medium Open allocated 16–90 MiB before refusing a row under any cap. Many small zstd frames cost 2 GB for a 22 KB row. Decoding bounded per cap into a buffer that cannot grow (≤ ~2.8× cap in every tested attack). Over-long blobs refused before decrypting. Tests measure allocation.
Medium CI fuzz jobs never ran (-fuzz over ./..., two packages) Target .; a test checks the command form
Medium Compression is a length oracle within one field (CRIME) Documented, plus Envelope.DisableCompression (a stored zstd frame, readable by any reader)
Medium README usage didn't compile and ignored errors (copied as written, it started a reader on a random key) Snippets handle errors and are compiled by a test
Medium Metadata integrity and the per-request binding were undocumented README, SPEC and ATTACK updated
Low All-zero keys; NewLocalKeyring(nil) silently ephemeral; inconsistent ErrInvalidConfig; unusable public keys accepted; unbounded hostile-row inputs; process-wide serialisation; test gaps All fixed (see CHANGELOG)

Other changes

  • HKDF comes from the standard library, so golang.org/x/crypto is dropped; the known-answer vectors are unchanged.
  • klauspost/compress is bumped to 1.20.0.
  • New vectors cover negative and non-ASCII bindings, unstamped rows and uncompressed rows.
  • CI runs on both the go.mod minimum and the latest 1.26 patch. Dependabot is enabled, and issue forms route security reports to SECURITY.md.
  • SECURITY.md gains supported versions and a response timeline. NOTICE and CODE_OF_CONDUCT are added.
  • All 6 translations are updated.

Verification

  • go vet, gofmt, go test -race ./... and staticcheck are all clean.
  • All 9 fuzz targets ran 30s each, run exactly as CI runs them.
  • The verifier's own attack suite passes against the final code, including 113 caps × compressed/uncompressed Seal/Open and stored frames checked against reference libzstd.
  • govulncheck could not run locally (vuln.go.dev is blocked in the sandbox); CI runs it.

Please check before merging

  • Legal entity in NOTICE ("Continuum AI Corp.") and the conduct contact in CODE_OF_CONDUCT (security@orcarouter.ai).
  • SECURITY.md response targets (3 / 10 / 90 days) are suggested defaults.
  • Compression default: it stays on, with an opt-out.

Note: CI may not run until the organization's Actions billing issue is resolved.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VwpTwdibuwvYAqEb4hETUu


Generated by Claude Code

OrcaRouter and others added 2 commits September 23, 2026 23:58
Code (each fix has a test that failed before it):
- Decoding is bounded per Envelope cap, in a buffer that cannot grow: a
  small row could make Open allocate 16-90 MiB, and a flood of small zstd
  frames 2 GB, before refusing it. Blobs longer than the cap allows are
  refused before decryption.
- Reseal, for a safe AuthKey cutover and AuthKey rotation.
- Envelope.DisableCompression: stored zstd frames, so a field's length no
  longer depends on its content (CRIME within one field).
- All-zero keys refused; NewLocalKeyring rejects an empty seed
  (NewEphemeralKeyring for tests); ErrInvalidConfig from every constructor;
  public keys that cannot be sealed to are refused at load.
- Hostile rows: leaf ids <= 256 bytes, sealed leaves exactly 1168 bytes,
  row values truncated in errors, partial cache eviction,
  RequireGenerationStamp.
- HKDF from the standard library (x/crypto dropped; vectors unchanged);
  klauspost/compress 1.20.0; concurrent encoders/decoders.
- Vectors for negative/non-ASCII bindings, unstamped and uncompressed rows.

CI: fuzz jobs now target one package (they never ran); tests on the go.mod
minimum and latest 1.26 patch; Dependabot; issue forms route security
reports to SECURITY.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VwpTwdibuwvYAqEb4hETUu
- The cutover no longer picks the envelope from schema_version (a column
  the forger writes): re-seal once with Reseal, then read authenticated
  only; the forgery window lasts until the migration finishes.
- Compression's in-field length oracle, unauthenticated metadata, the
  per-request binding and compromised writers are documented.
- README usage snippets handle errors and are compiled by a test; install
  line; aligned diagrams; 'hybrid post-quantum' instead of 'quantum-safe'.
- SPEC, ATTACK and CHANGELOG updated; 'audit' becomes 'internal review'.
- SECURITY.md: supported versions and response timeline; NOTICE and
  CODE_OF_CONDUCT added.
- All six translations updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VwpTwdibuwvYAqEb4hETUu
@yi-here
yi-here merged commit 44b5d16 into main Sep 24, 2026
1 of 5 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.

1 participant