sec: answer the advisory gate's first catch, remove hpke-rs 0.2.0, and clear every yanked dependency #449
Loading…
Reference in a new issue
No description provided.
Delete branch "sec/unsound-bumps-2026-10"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Advisory follow-ups to #443, rebased onto main (which #447 fixed — the
joule-moq-roomlockfile failure on the first attempt was that pre-existing breakage, red on main since #427, not this branch).The gate caught something on its first real run
Two advisories published 2026-10-23, after the sweep in #443 was done. Both are constant-time failures:
ctutilsu128comparisons. Reaches openpay's wallet crates viadigest → hmac/hkdf, so it sits under HMAC on payment paths.crypto-bigintThe 0.5.5 line of crypto-bigint cannot follow:
elliptic-curve0.13 pins it, so reaching ≥0.7.6 means moving the p256/elliptic-curve stack across openpay, sandbox, wai and jouleclaw. That is an upgrade, not a bump. It is allowed with that reason recorded, on paths that sign and derive keys, so it reads as debt rather than a verdict.Writing that allowance exposed a hole in the check
ALLOWwas keyed by advisory id alone, so an entry excusing the stuck 0.5.5 line would have gone on excusing the advisory if a patched 0.7.x copy later regressed — the same shape as sealing by name instead of by digest. An entry may now pin the exact pairs it covers:Any other version of that crate fails, and a named pair that disappears makes the entry stale, so the pin cannot keep describing a tree that moved. The version-blind string form stays for reasons that genuinely do not depend on version (a call we never make), and the two forms are documented against each other. The self-test now builds its documents by importing the real
ALLOWinstead of scraping it with grep, so the two cannot drift, and covers both new failure modes.Also in this branch
hpke-rs 0.2.0removed — this was written for #443 but never landed: that PR merged at4e7fa646ewhile this commit was still in flight, so main kept the old openmls 0.6/0.3 dev-dep stack and its four advisories. Pinningjoule-code-collab's dev-deps to the generationjoule-moq-mlsalready runs removes hpke-rs 0.2.0, hpke-rs-crypto, hpke-rs-rust-crypto and openmls 0.6.0 outright, and with them RUSTSEC-2026-0069/-0070/-0071 (9.3)/-0072.mls_keyingpasses. It also carries the correction that the openpay quick-xml copy is not on a parse path.anyhow1.0.103 (RUSTSEC-2026-0190),event-listener5.4.2 (-0221),lru0.18.2 (-0253, a potential use-after-free inLruCache::pop()).chacha200.10.0/0.10.1 → 0.10.2 (a cipher, six lockfiles),der0.8.0 → 0.8.2,spin0.9.8 → 0.9.9 and 0.10.0 → 0.10.1,iroh-blobs0.101.0 → 0.101.1. A yank is the author withdrawing a release; none of these needed to stay on one. No yanked dependency remains anywhere.Remaining unsound, recorded rather than left unexplained:
im15.1.0 andsized-chunks0.6.5 have no fixed release at all (both unmaintained; the sized-chunks one is use-after-free / double-free), whilelru0.12.5,rand0.7.3 andglib0.18.5 each need a semver-major move and are transitive.Verified: all 47 lockfiles current, advisory check green at 15 documented allowances, self-test green on all six cases, and the affected workspaces check clean with
mls_keyingpassing.🤖 Generated with Claude Code
Carries
cfd341b05fromsec/after-443-b(#456 closed in favour of this)The quick-xml 0.36 → 0.41 bump in #443 left two things behind in jouleclaw, both mine: three calls to
Attribute::unescape_value, which 0.41 deprecates, and — from moving the TRX dispatch out of theEvent::Textarm — fourin_*flags and acur_field_valueround-trip that were assigned and never read.That fails the last step of the macOS energy job (
.github/workflows/standards-build.yml:577-581), which runscargo clippy --all-targets --no-deps -- -D warningsoverjouleclaw-loader-gguf. The test step in the same job only warns and passes, which is why this looked green from the wrong angle.normalized_value(XmlVersion::Implicit1_0)is upstream's own prescribed replacement and still resolves entities —normalized_value_with(version, 1, resolve_predefined_entity)— so it does not reintroduce the silent entity-dropping this branch's parent fixed. The transform-trx half is semantically equivalent:cur_field_valuewas assigned then immediately.take()n.Verified on a macOS host against the exact command:
-p jouleclaw-loader-ggufand-p jouleclaw-transform-trxboth exit 0 under-D warnings, with no deprecated and no unused-variable errors.`cargo audit` reports 67 warnings the advisory gate deliberately does not fail on, because maintenance advice would bury the reachable defects. Nine of them are not maintenance advice though — they are unsoundness, and one is a use-after-free. Three have a semver-compatible fix: anyhow 1.0.102 -> 1.0.103 RUSTSEC-2026-0190, unsoundness in `Error::downcast_mut()` event-listener 5.4.1 -> 5.4.2 RUSTSEC-2026-0221, `!Send` tags crossing a thread boundary via `StackSlot` lru 0.18.0 -> 0.18.2 RUSTSEC-2026-0253, potential use-after-free from missing panic safety in `LruCache::pop()` All three are in smart-byte-rs, which still checks clean. The remaining six are recorded here rather than left unexplained: - `im` 15.1.0 (RUSTSEC-2023-0126, aliasing violation in `OrdSet` insertion) and `sized-chunks` 0.6.5 (RUSTSEC-2026-0255, panic-safety unsoundness in `Chunk`/`RingBuffer`/`InlineArray` — use-after-free and double-free) have **no fixed release at all**; both crates are unmaintained. - `lru` 0.12.5 (RUSTSEC-2026-0002, -0253), `rand` 0.7.3 (RUSTSEC-2026-0097) and `glib` 0.18.5 (RUSTSEC-2024-0429) need a semver-major move, and all three are transitive, so the dependent has to move first. Co-Authored-By: Claude Opus 5 <[email protected]>0ad2d8f50c4bbb4cd254sec: take the three unsoundness fixes that are a patch bump awayto sec: answer the advisory gate's first catch, remove hpke-rs 0.2.0, and clear every yanked dependency