Repository navigation
fix(deps): clear five RustSec advisories (webpki, wasmtime, p256 0.14 for crypto-bigint) - #480
Merged
Merged
Conversation
…visories rustls-webpki 0.103.15 -> 0.103.16 (RUSTSEC-2026-0382) and webpki-roots 1.0.8 -> 1.0.11 (RUSTSEC-2026-0381) in both lockfiles, the workspace and crates/cluster. wasmtime 49.0.3 -> 49.0.4 (RUSTSEC-2026-0378, RUSTSEC-2026-0379) in the workspace lockfile only, staying on 49.x; the cranelift and pulley crates move with it from 0.136.3 / 49.0.3 to 0.136.4 / 49.0.4. Lockfile-only: no manifest changes, no new crate. crypto-bigint 0.5.5 (RUSTSEC-2026-0387) is the fifth advisory and needs the p256 0.14 migration in the next commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKcmLyFYX5vcY81ze4tHQ1
…026-0387) p256 0.13 is pulled only by this workspace's own crates (cloud, delegation, dpop, gateway). Moving all six manifest lines to 0.14 brings elliptic-curve 0.14.3, ecdsa 0.17.0, pkcs8 0.11, sec1 0.8, signature 3.0 and rfc6979 0.6, and replaces crypto-bigint 0.5.5 with 0.7.9, so `cargo tree -i crypto-bigint --all-features --target all` no longer shows a 0.5.x. The code changes are two renames, nothing else: - `VerifyingKey::to_encoded_point(compress)` is `to_sec1_point(compress)` in ecdsa 0.17; `x()`, `y()` and `as_bytes()` on the result are unchanged. - `SigningKey::random(&mut OsRng)` is deprecated, and rand_core is 0.10 with no `OsRng`; the test fixtures that made a random key now call `<SigningKey as p256::elliptic_curve::Generate>::generate()`. Production key generation (gateway checkpoints) already drew bytes with getrandom 0.2 and `SigningKey::from_slice`, which is unchanged. `Signature::from_slice`, `to_bytes`, `VerifyingKey::from_sec1_bytes`, `SecretKey::from_pkcs8_pem` / `from_sec1_pem` / `from_pkcs8_der` / `from_sec1_der` keep their names and signatures. P-256 keeps `NORMALIZE_S = false`, so a high-S signature still verifies and signing still does not normalise s, as in 0.13. One rustfmt collapse in an audit_sign test follows the shorter name; the assertion is the same. The gateway manifest comment on hmac is corrected: hmac 0.12 reached the lockfile through p256 0.13's rfc6979, and since 0.14 (which uses hmac 0.13) the gateway's own line is its only edge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKcmLyFYX5vcY81ze4tHQ1
The external P-256 values the suite already checked were three keyryx thumbprints (measured from keyryx's Go code) and agent-passport's checkpoint vectors, which it verifies but does not produce. Nothing held a signature this code produces, a SEC1 public key, or a PKCS#8 / SEC1 private key parse to an external value, so a curve library that changed one of those could pass the suite as long as it agreed with itself. Three tests now hold the bytes to RFC 6979 appendix A.2.5 (a P-256 key, its point, its deterministic SHA-256 signatures), with the base64 forms, the RFC 7638 thumbprint and the PKCS#8 / SEC1 encodings written out by Python `cryptography` 50.0.1, never by p256: - gateway::checkpoints: the checkpoint key's JWK x and y, its kid, and the raw r||s over "sample" and "test". - cloud::devices: the RFC signature verifies under the uncompressed and compressed SEC1 key; with its halves swapped, or in DER, it is refused. - cloud::audit_sign: the RFC key loads from PKCS#8 PEM, SEC1 PEM, PKCS#8 DER, SEC1 DER and a raw scalar, and each signs the same empty-chain manifest to the same public key and signature bytes. Each went red against a deliberately broken encoding first (padded standard base64 for x and y; s before r; a DER-only signature parser; a compressed public key and a DER signature in the manifest) and green on the real code. All three also pass unchanged on main with p256 0.13.2, so 0.13 and 0.14 put the same bytes on the wire. Encoding the manifest's public key compressed passed every older test; only the new one caught it. Scenarios: features/the-p256-wire-format-is-unchanged.feature, five, each bound. The suite goes from 2414 to 2417; README.md and PROGRESS.md say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKcmLyFYX5vcY81ze4tHQ1
`secretscan / tree` flagged the PKCS#8 header of the RFC 6979 appendix A.2.5 P-256 key that the audit-signing-key encoding test loads (crates/cloud/src/audit_sign.rs, fingerprint 3021d90eb9437b2d, the same header fingerprint already allowed for the test keys in crates/cloud/tests/it/oidc.rs and crates/dpop/src/lib.rs). The key is a published test vector and signs nothing. The SEC1 header in the same file was already covered by its existing entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKcmLyFYX5vcY81ze4tHQ1
TAIPANBOX
marked this pull request as ready for review
October 26, 2026 04:05
TAIPANBOX
enabled auto-merge
October 26, 2026 04:05
This was referenced Oct 26, 2026
TAIPANBOX
added a commit
that referenced
this pull request
Oct 26, 2026
check_statement requires a non-empty `signatures` list before it reads a statement (the witness verifies the signatures, invariant 128), but no test served a statement without one, so a mutant that dropped the check survived the p256 0.14 PR's mutation run (#480). The keyryx stub gains two modes, no `signatures` and an empty list, and both must be refused as not of the known shape. One scenario, bound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
security (cargo audit)has been red on every PR since five RustSec advisories were published. This makes./scripts/audit.sh(both audited lockfiles pluscrates/radar) pass again by upgrading the affected crates..cargo/audit.tomlis unchanged: no new ignore.crates/clustercrates/clustercrypto-bigint 0.5.5 was reachable only through p256 0.13, which only this workspace's own crates depend on (cloud, delegation, dpop, gateway). So the fifth advisory is fixed by moving p256 to 0.14 (elliptic-curve 0.14.3, ecdsa 0.17.0, pkcs8 0.11, sec1 0.8, signature 3.0, rfc6979 0.6).
Commits
fix(deps): patch rustls-webpki, webpki-roots and wasmtime for four advisories: lockfile-only patch bumps, resolved againstmain's manifests.fix(deps): move p256 to 0.14, dropping crypto-bigint 0.5.5: six manifest lines plus two API renames, nothing else:VerifyingKey::to_encoded_point(compress)is nowto_sec1_point(compress);x(),y(),as_bytes()are unchanged.SigningKey::random(&mut OsRng)is deprecated and rand_core 0.10 has noOsRng. The four test fixtures that made a random key now call<SigningKey as p256::elliptic_curve::Generate>::generate(). Production key generation (gateway checkpoints) already used getrandom 0.2 bytes andSigningKey::from_slice, unchanged.Signature::from_slice/to_bytes,VerifyingKey::from_sec1_bytes, andSecretKey::from_pkcs8_pem/from_sec1_pem/from_pkcs8_der/from_sec1_derkept their names and signatures.NORMALIZE_S = falsein ecdsa 0.17 (p256-0.14.0/src/ecdsa.rs,ecdsa-0.17.0/src/hazmat.rs), so a high-S signature still verifies and signing still does not normalise s, as in 0.13.hmacwas stale after the bump and is corrected: hmac 0.12 came in through p256 0.13's rfc6979; now the gateway's own line is its only edge.test(crypto): pin the P-256 wire bytes to RFC 6979's published vector: three new tests, a feature file, and the test count.test(crypto): allow-list the RFC 6979 test key for the secret scan: one.secretscan-allowline.secretscan / treeflagged the PKCS#8 header of the RFC 6979 key inaudit_sign.rs(fingerprint3021d90eb9437b2d, the same header fingerprint already allowed for the test keys inoidc.rsanddpop/src/lib.rs). It is a published test vector and signs nothing; the SEC1 header in that file was already covered.Existing tests
No assertion changed. Test files changed only where an API was renamed (
to_encoded_pointtoto_sec1_point, the random-key constructor), plus one rustfmt line collapse inaudit_sign::tests::base64_raw_scalar_key_round_tripsthat follows the shorter name.Wire format: what pins it
Before this PR the external P-256 values the suite checked were the three keyryx thumbprints measured from keyryx's Go code (
KID_11/22/33) and agent-passport's checkpoint vectors, whichthe_vector_signatures_verify_under_the_vector_keyverifies but does not produce. Nothing held a signature this code produces, a SEC1 public key, or a PKCS#8 / SEC1 private key parse to an external value. The new tests use RFC 6979 appendix A.2.5 (a P-256 key, its public point and its deterministic SHA-256 signatures). The base64 forms, the RFC 7638 thumbprint, the compressed point, the DER signature and the PKCS#8 / SEC1 encodings were computed with Pythoncryptography50.0.1, which also verified both RFC signatures under the RFC point and reproduced the RFC's "sample" signature with its deterministic ECDSA.gateway::checkpoints::tests::the_rfc_6979_key_puts_its_published_point_and_signatures_on_the_wirex/y(base64url, no padding),kid(RFC 7638), raw r||s over "sample" and "test"cloud::devices::tests::a_published_rfc_6979_signature_verifies_and_no_other_encoding_of_it_doesSignature::from_derin place offrom_slicecloud::audit_sign::tests::the_rfc_6979_key_loads_from_every_accepted_encoding_and_signs_a_known_manifestpublic_key_b64andsignature_b64Encoding the manifest's public key compressed passed every older test; only the new test caught it.
All three new tests were also run unchanged on
main(p256 0.13.2, crypto-bigint 0.5.5, compiled in a separate worktree): all pass. Both versions therefore produce the RFC's bytes. Separately,the_committed_fixture_is_what_the_writer_writes_byte_for_byte(checkpoint records and signatures written with p256 0.13) passes on 0.14.Scenarios:
features/the-p256-wire-format-is-unchanged.feature, five, each bound (features-are-bound.sh: 888 scenarios, 1248 bindings, 0 broken).Mutation check (not committed)
Each mutant was planted in product code, run, and reverted (files compared byte for byte afterwards).
dpop::verify_proof: a signature failure (ErrorKind::InvalidSignature) is accepted by decoding again with signature validation disableddpop::tests::a_proof_signed_by_a_key_other_than_the_one_it_carries_is_refused(plus three RSA bound tests)audit_sign::build_signed_manifestsigns with another key than the one it publishesmanifest_signature_verifies_and_pins_the_tip,empty_chain_signs_a_valid_zero_tip_manifest, the new RFC test;tests/it:audit_manifest::manifest_signature_verifies_and_matches_chain,empty_chain_signs_a_valid_zero_tip_manifest,manifest_tip_moves_after_a_new_mutationcheckpoints::check_statementaccepts a keyryx statement with nosignaturestests/it/event_checkpointstests green)checkpoints::check_statementaccepts a statement certifying another keycheckpoints::tests::a_statement_that_does_not_certify_this_key_is_refusedDelegatedSigner::key_atignores the statement windowa_key_signs_only_inside_its_statement_window_in_whole_seconds,a_key_past_its_statement_is_never_used_and_the_record_is_unsigned,a_key_that_runs_out_mid_stream_gives_unsigned_records_not_stale_signatures,the_committed_fixture_is_what_the_writer_writes_byte_for_bytecheckpoints.rsis a writer and verifies no signature itself (invariant 128 leaves the statement's root signatures to the witness); the presence check onsignaturesis the nearest thing and has no test. That gap predates this PR and is left for a follow-up rather than widening this one.Gates run locally
cargo fmt --all -- --check: clean (workspace andcrates/cluster).cargo clippy --workspace --all-targetswith featurescluster,wasm,apns,testing: 0 warnings.--all-featurescould not complete here becauseort-sys(theonnxfeature, unchanged) downloads ONNX Runtime in its build script and this sandbox blocks the host; CI's--all-featuresrun covers it.cargo test --all --no-fail-fast: 2417 tests, 2415 passed as root; the two that need a 0500 directory failed as root (invariant 78) and passed when re-run withdac_overridedropped. Two further full runs without those capabilities: 2417 passed, 0 failed.cargo test -p tokenfuse-gateway --features cluster --test cluster_backend: 6 passed.crates/cluster: clippy 0 warnings, 13 tests pass../scripts/audit.sh: exit 0. Before this PR it stopped aterror: 5 vulnerabilities found!on the workspace lockfile. After: no vulnerability in the workspace,crates/clusterorcrates/radar; the remaining output is the existing warnings (unmaintained, unsound, yanked), which cargo-audit reports as allowed.cargo tree -i crypto-bigint --all-features --target all: only 0.7.9;crypto-bigint@0.5.5matches no package../scripts/stated-numbers.sh(run without DAC override): 2417, README badge and PROGRESS.md agree. A first run reported the three figures one off, consistent with one test failing once; it did not repeat in three later full runs and was not identified.constants.sh,d9-send-retention.sh,core-deps.sh,dto-boundary.sh,replicated-shape.sh,honest-claims.sh,features-are-bound.sh,runnable-quickstart.sh,pinned-installs.sh,compat-surface.sh,one-test-binary-per-crate.sh,no-owner-quotes.sh,no-html-from-data.sh,teeth-shards-cover-every-case.sh,attestation-is-derived.sh,run-owner-is-checked-first.sh,upstream-key-is-never-forwarded.sh,cloud-credentials-are-digested.sh,dashboard-key-stays-out-of-the-query.sh,client-keys-are-digested.sh,both-processes-configure-the-same-doors.sh: all pass../scripts/gates-have-teeth.shafter the commits: 237 cases, every oneok, exit 0 (run withdac_overrideanddac_read_searchdropped; as root the threestated-numberscases are UNJUDGEABLE because the gate already fails on the two root-only tests).secretscan / tree) lives in another repository and was not run locally; CI runs it.Not proven
apns.rs) has no fixed-vector test: it signs with the sameSigningKey::signandto_bytes()the checkpoint test pins, but mints at the current time.onnxfeature was not built here (see clippy above).🤖 Generated with Claude Code
https://claude.ai/code/session_01HKcmLyFYX5vcY81ze4tHQ1