fix(security): wasmtime 43 -> 47.0.4 -- the real fix for RUSTSEC-2026-0269, and it needed ZERO source changes - #2807
fix(security): wasmtime 43 -> 47.0.4 -- the real fix for RUSTSEC-2026-0269, and it needed ZERO source changes#2807noahgift wants to merge 1 commit into
Conversation
pr-review v2.0.0 — automated adversarial review (PR-REVIEW-SKILL-002-v2)5 findings raised, 2 survived adversarial refutation (three independent verifiers per finding — correctness / scope / evidence-quality lenses, refute-by-default). Refuted findings are dropped, not shown.
1. Cargo.toml's new MSRV comment asserts a coverage claim that files in the same commit falsify — six --all-features call sites DO build wasmtime, and they now hard-fail on the pinned toolchain
Evidence Why it matters — The comment is the only place a future reader looks before touching the toolchain pin or the wasmtime version, and it tells them a falsehood about Why this survived refutationFinding survives all five refutation gates; every claim reproduced independently. (1) INTRODUCED BY THIS PR, not main: 2. The contract now ships two falsification tests whose
|
3dcc33b to
5cf61b4
Compare
…-0269, and it needed ZERO source changes RUSTSEC-2026-0269 (CVSS 8.8, filesystem sandbox escape, published 2026-08-20) took the required ci / security check red on every open PR at once. #2805 contained it by adding the id to .cargo/audit.toml. This is the fix that makes the containment temporary rather than permanent. The same bump had already been deferred once, in writing, in the RUSTSEC-2026-0222 note in that same file: The fix is a real upgrade, not this line: 43 -> >=46.0.2,<47 or >=47.0.3, a four-major jump on a test-only dep. Tracked separately; revisit before anything starts enabling runtime. That premise is wrong. crates/aprender-test-lib/src/runtime.rs is the only file in the workspace that touches wasmtime -- a bare Linker with four host functions -- and every API it uses is unchanged in 47. The bump is one manifest line: cargo check -p aprender-test-lib --features runtime @ 43 -> exit 0 (baseline) cargo check -p aprender-test-lib --features runtime @ 46.0.3 -> exit 0, no edits cargo check -p aprender-test-lib --features runtime @ 47.0.4 -> exit 0, no edits cargo test -p aprender-test-lib --features runtime -- runtime -> 73 passed, 0 failed Ten wasmtime/cranelift exemptions are now deletable, verified by REMOVING them rather than by assertion. Reproduced with the reusable workflow's exact command shape (sed the RUSTSEC ids out of .cargo/audit.toml into --ignore flags): origin/main audit.toml + wasmtime 43 lock -> exit 1, 1 vulnerability, 9 warnings trimmed audit.toml + wasmtime 47 lock -> exit 0, 0 wasmtime/cranelift, 5 warnings Mutation-verified: revert the lock to 43 with the trimmed list and it turns RED again (exit 1, RUSTSEC-2026-0269 and RUSTSEC-2026-0222 both firing); restore 47 and it goes green. Allowed warnings drop 9 -> 5 because bitmaps, im-rc and sized-chunks (x2) entered solely through cranelift 0.130 and are gone at 0.134. No warning became an error and nothing new appeared. MSRV, stated plainly rather than buried: wasmtime >=46 requires Rust 1.94.0 and rust-toolchain.toml pins 1.93.0. CI stays green regardless, because runtime is optional and NOTHING in the workspace, .github/workflows/, scripts/ or the Makefile enables it, so cargo never builds wasmtime and the MSRV check never fires (cargo check -p aprender-test-lib under 1.93 with the 47 lock: exit 0). The honest cost is that --features runtime now needs Rust 1.94+ until the pin moves; cargo fails with an explicit MSRV message, not silently. The toolchain bump is deliberately NOT bundled here -- measured separately, cargo +1.95 check --workspace is clean but clippy surfaces ~56 new code lints that would fail under -D warnings. Tracked in #2806. Reachability was re-verified from scratch, not inherited. The check needed a positive control first: an early pattern matched the worktree path itself and made every tree look full of wasmtime. Validated against a known-true case (-p aprender-test-lib --features runtime -> 35 matches) before any zero was trusted; all trees non-empty. 0 wasmtime in -p aprender, --no-default-features, --all-features, -p apr-cli, -e normal, and --workspace; 35 only under --workspace --all-features, which no CI lane runs. Second, independent reason it was never exploitable: per GHSA-vqjp-4c8c-hfgg the vulnerable code is in wasmtime-wasi, which is not in Cargo.lock at all. The vulnerable code was not merely unreachable, it was not compiled. contracts/wasmtime-upgrade-v1.yaml goes to 2.0.0. Its advisory_elimination equation ("zero wasmtime entries in .cargo/audit.toml") was FALSE for the entire life of the 43.x cluster and nothing noticed -- none of its FALSIFY-WASM tests are wired into CI. This commit makes the equation true; wiring the falsifiers is noted in #2806. Refs #2806, #2805, RUSTSEC-2026-0269, GHSA-vqjp-4c8c-hfgg Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> REBASED onto main at 75b178a (2026-08-31). The conflict was semantic, not textual: #2805 landed its containment line for the sandbox escape INSIDE the exemption block this commit deletes. Resolved in this commit's favour -- eleven ids go, not ten, because the containment entry is obsolete for exactly the same reason as the 43.x cluster it was appended to. Re-verified after the rebase with the reusable workflow's own command shape, not by assertion: main 75b178a as-is (43 lock, 31 ignores) -> exit 0, 9 allowed warnings main 75b178a lock + this commit's audit.toml -> exit 1, 2 vulnerabilities RUSTSEC-2026-0269 8.8 high AND RUSTSEC-2026-0222 3.8 low both fire this commit (47.0.4 lock, 20 ignores) -> exit 0, 5 allowed warnings The middle line is the mutation: hold the trimmed ignore list fixed and revert only the lockfile, and the gate turns RED. So the green on the third line is the bump doing the work, not a shorter list hiding it. Reported-advisory sets diffed rather than eyeballed: nothing new appeared, and four went away (bitmaps, im-rc, sized-chunks x2 -- all cranelift 0.130-only; 0.130.2 -> 0.134.4). Both inherited claims were re-checked rather than trusted. No CI lane builds the runtime feature: `all-features` occurs ZERO times in all of .github/workflows/, ci.yml's mutants job runs `cargo mutants --in-diff -- --lib`, `make coverage` is `--workspace --exclude aprender-gpu --lib`, and no workflow invokes test-full / coverage-full / mutants. Reachability re-measured with a positive control FIRST (`-p aprender-test-lib --features runtime` -> non-zero, so a zero elsewhere means something): 0 wasmtime for -p aprender, -p aprender --no-default-features, -p apr-cli, --workspace, --workspace -e normal, and -p aprender-test-lib at its defaults. And the MSRV pin does not need to move: under the pinned rustc 1.93.0, `cargo metadata --locked` and `cargo check --locked -p aprender-test-lib --lib` both exit 0 against the 47 lock, so rust-version = "1.91" stays put too. deny.toml carried a stale "wasmtime 43 + cranelift ... Upgrade to >=43.0.2 when available" comment. It is deleted here, which makes this contract's advisory_elimination invariant ("deny.toml has zero wasmtime entries") true on purpose rather than by accident -- cargo-deny never read that line either way. `cargo deny check` -> advisories ok, bans ok, licenses ok, sources ok.
5cf61b4 to
7104c4e
Compare
|
PP-066 triage (epic #2873, ticket #2986): MERGE-NOW (security advisories first; linked issue #2806 sits in C0-1's list, whose cargo-deny job stays red until this lands). Rebased onto |
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
Closes #2806. Follows #2805 (the containment) with the actual fix.
What this is
#2805 stopped the bleeding by adding RUSTSEC-2026-0269 to
.cargo/audit.toml. That wasthe right andon call. This PR is the reason it stays a containment instead of becoming
the twelfth permanent exemption: wasmtime moves 43 -> 47.0.4 and all ten wasmtime
exemptions are deleted.
The same bump was already deferred once, in writing, in the
RUSTSEC-2026-0222note:That premise does not survive contact.
crates/aprender-test-lib/src/runtime.rsis theonly file in the workspace that touches wasmtime — a bare
Linkerwith four host functions— and every API it uses is unchanged in 47. There is no API work. The diff is one manifest
line plus the lock.
Verification
Baseline reproduced before anything changed, using the reusable workflow's exact
command shape (
sedthe RUSTSEC ids out of.cargo/audit.tomlinto--ignoreflags):origin/mainaudit.toml + wasmtime 43 lockerror: 1 vulnerability found!, 9 allowed warnings, RUSTSEC-2026-0269 presentCompile and test, with the feature actually enabled (a
cargo check --workspaceneverbuilds an optional feature and would have proved nothing):
cargo check -p aprender-test-lib --features runtime@ 43 (baseline)cargo +1.95 check -p aprender-test-lib --features runtime@ 46.0.3cargo +1.95 check -p aprender-test-lib --features runtime@ 47.0.4cargo +1.95 test -p aprender-test-lib --features runtime --lib -- runtimeMutation-verified rather than asserted — the exemptions were proved obsolete by deleting
them, not by reasoning:
Deleted as obsolete:
RUSTSEC-2026-0085 / -0086 / -0088 / -0089 / -0091 / -0092 / -0094 / -0096 / -0114 / -0222.Allowed warnings drop 9 -> 5:
bitmaps,im-rcandsized-chunks(x2) entered solelythrough cranelift 0.130's tree and are gone at 0.134. No warning became an error, and
nothing new appeared.
The one real tradeoff, stated plainly
wasmtime >=46 requires Rust 1.94.0;
rust-toolchain.tomlpins 1.93.0. Both fixedlines (46.0.3 and 47.0.4) need 1.94.
CI stays green anyway, and this was checked rather than assumed:
cargo check -p aprender-test-lib(default features, rustc 1.93.0, wasmtime 47 in thelock) exits 0.
runtimeis optional and nothing in the workspace,.github/workflows/,scripts/or theMakefileenables it, so cargo never buildswasmtime and the MSRV check never fires.
The honest cost:
--features runtimenow needs Rust 1.94+ until the pin moves. Thefeature is already dark, and cargo fails with an explicit MSRV message rather than
silently — but it is a real regression and is documented at the dep declaration, not
buried. The toolchain bump is deliberately not bundled here; measured separately,
cargo +1.95 check --workspaceis clean (0 errors) but clippy surfaces ~56 new code lintsacross ~11 classes that would fail under
-D warnings. That belongs in its own PR (#2806).Reachability, re-verified from scratch
Not inherited from the audit.toml note. The check needed a positive control first: an early
pattern matched the worktree path
/home/noah/src/aprender-wasmtime-fix/itself and madeevery tree look full of wasmtime. Pattern validated against a known-true case
(
-p aprender-test-lib --features runtime-> 35 matches) before any zero was trusted, andevery tree below is non-empty.
cargo tree -p aprendercargo tree -p aprender --no-default-featurescargo tree -p aprender --all-featurescargo tree -p apr-clicargo tree -p apr-cli --all-featurescargo tree -e normal -p aprendercargo tree --workspacecargo tree --workspace --all-featuresNo CI lane runs
--workspace --all-features:make coverage(coverage-nightly.yml) is--workspace --exclude aprender-gpu --lib, andcargo mutants(ci.yml) is-- --lib. The--all-featurestargets that would pull it in (test-full,coverage-full) are notCI-wired.
Second, independent reason it was never exploitable: per GHSA-vqjp-4c8c-hfgg the vulnerable
code lives in
wasmtime-wasi, which is not inCargo.lockat all. The vulnerable codewas not merely unreachable — it was not compiled.
Also in here
contracts/wasmtime-upgrade-v1.yaml-> 2.0.0. Itsadvisory_eliminationequation ("zerowasmtime entries in
.cargo/audit.toml") was false for the entire life of the 43.xcluster and nothing noticed — none of its FALSIFY-WASM tests are wired into CI
(
grep -rn "wasmtime-upgrade\|FALSIFY-WASM" .github/ scripts/ Makefilereturns nothing).This PR makes the equation true. Wiring the falsifiers so it can fail again is noted in
#2806 as the dark-target class.
pv validate contracts/wasmtime-upgrade-v1.yaml-> 0 errors, 0 warnings.Merge order
Land after #2805. This branch is cut from
origin/mainand will conflict with it in.cargo/audit.toml; resolve by taking this side and additionally deleting #2805'sRUSTSEC-2026-0269line, which this bump makes obsolete.cargo auditmust come outexit 0 with zero wasmtime ids in the file.