From 1a514b243c69e394ed2a19186f9411102b07bb12 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Mon, 26 Oct 2026 11:32:36 -0400 Subject: [PATCH 1/2] sec: zstd 0.14.3 for RUSTSEC-2026-0391, -0398, -0403 and -0410 Four advisories against the zstd crates, published October 2026, failed the repository check on every pull request: - RUSTSEC-2026-0391 (zstd < 0.14.3): data from an abandoned stream leaks into the next stream on a reused context; - RUSTSEC-2026-0398 (zstd-safe < 8.2.0): Seekable::decompress sets a Vec length past its capacity; - RUSTSEC-2026-0403 (zstd-safe < 8.2.0): uninitialised memory when a legacy frame's streaming decompression fails; - RUSTSEC-2026-0410 (zstd-sys < 2.1.2): the wasm allocator shim corrupts memory on allocation failure. Every direct use moves: wai (zstd 0.14.3, zstd-safe 8.2), jwp and joule-moq-interop (zstd 0.14.3). Five lockfiles change exactly the three zstd packages and nothing else: wai-rs, wai-rs/fuzz, joule-code-rs, joule-moq-room and examples/transport-moqt. The one copy left is wasmtime 49's, under wasmtime-internal-cache, which compresses compiled modules for wasmtime's on-disk cache. sandbox-exec-wasm builds its engine from Config::new() with fuel metering only and never configures a cache, so zstd's code does not run in the sandbox. It is allowed in scripts/check-advisories.py at those exact versions, so a direct use regressing to them is not excused. Co-Authored-By: Claude Opus 5.5 --- joule-code/examples/transport-moqt/Cargo.lock | 12 ++++----- joule-code/joule-code-rs/Cargo.lock | 12 ++++----- .../crates/joule-moq-interop/Cargo.toml | 2 +- .../crates/joule-moq-room/Cargo.lock | 12 ++++----- .../joule-code-rs/crates/jwp/Cargo.toml | 2 +- scripts/check-advisories.py | 25 +++++++++++++++++++ wai/wai-rs/Cargo.lock | 12 ++++----- wai/wai-rs/Cargo.toml | 4 +-- wai/wai-rs/fuzz/Cargo.lock | 14 +++++------ 9 files changed, 60 insertions(+), 35 deletions(-) diff --git a/joule-code/examples/transport-moqt/Cargo.lock b/joule-code/examples/transport-moqt/Cargo.lock index 867c9a4a7..67033ca10 100644 --- a/joule-code/examples/transport-moqt/Cargo.lock +++ b/joule-code/examples/transport-moqt/Cargo.lock @@ -1339,27 +1339,27 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zstd" -version = "0.13.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +checksum = "db3ae9bf90af6e40197bef767eeefc46ad6397420fe873830bd85e5fbbfb3c70" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.4" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +checksum = "ded520f16b29e1a9b771c722221b2b0a0398c2316d9bb3c42b458a5414d7434b" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" +version = "2.1.2+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +checksum = "481ada9c543b2323cbb7bbdbb5249177fbf0188ed959ed2c15e4b22421c84ed3" dependencies = [ "cc", "pkg-config", diff --git a/joule-code/joule-code-rs/Cargo.lock b/joule-code/joule-code-rs/Cargo.lock index 9f3a11d43..c9890f0f6 100644 --- a/joule-code/joule-code-rs/Cargo.lock +++ b/joule-code/joule-code-rs/Cargo.lock @@ -4764,27 +4764,27 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zstd" -version = "0.13.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +checksum = "db3ae9bf90af6e40197bef767eeefc46ad6397420fe873830bd85e5fbbfb3c70" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.4" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +checksum = "ded520f16b29e1a9b771c722221b2b0a0398c2316d9bb3c42b458a5414d7434b" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" +version = "2.1.2+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +checksum = "481ada9c543b2323cbb7bbdbb5249177fbf0188ed959ed2c15e4b22421c84ed3" dependencies = [ "cc", "pkg-config", diff --git a/joule-code/joule-code-rs/crates/joule-moq-interop/Cargo.toml b/joule-code/joule-code-rs/crates/joule-moq-interop/Cargo.toml index 2bd88319e..e72fb65a7 100644 --- a/joule-code/joule-code-rs/crates/joule-moq-interop/Cargo.toml +++ b/joule-code/joule-code-rs/crates/joule-moq-interop/Cargo.toml @@ -22,7 +22,7 @@ tokio = { version = "1", features = ["rt-multi-thread", "macros", bytes = "1" ed25519-dalek = { version = "2", features = ["rand_core"] } serde_json = "1" -zstd = "0.13" +zstd = "0.14.3" hex = "0.4" async-trait = "0.1" blake3 = "1" diff --git a/joule-code/joule-code-rs/crates/joule-moq-room/Cargo.lock b/joule-code/joule-code-rs/crates/joule-moq-room/Cargo.lock index af0d1a600..c8264e6e5 100644 --- a/joule-code/joule-code-rs/crates/joule-moq-room/Cargo.lock +++ b/joule-code/joule-code-rs/crates/joule-moq-room/Cargo.lock @@ -3928,27 +3928,27 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zstd" -version = "0.13.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +checksum = "db3ae9bf90af6e40197bef767eeefc46ad6397420fe873830bd85e5fbbfb3c70" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.4" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +checksum = "ded520f16b29e1a9b771c722221b2b0a0398c2316d9bb3c42b458a5414d7434b" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" +version = "2.1.2+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +checksum = "481ada9c543b2323cbb7bbdbb5249177fbf0188ed959ed2c15e4b22421c84ed3" dependencies = [ "cc", "pkg-config", diff --git a/joule-code/joule-code-rs/crates/jwp/Cargo.toml b/joule-code/joule-code-rs/crates/jwp/Cargo.toml index 1e441bb09..497250ffb 100644 --- a/joule-code/joule-code-rs/crates/jwp/Cargo.toml +++ b/joule-code/joule-code-rs/crates/jwp/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" thiserror = "2" tracing = "0.1" -zstd = "0.13" +zstd = "0.14.3" lz4_flex = "0.13" futures-util = { version = "0.3", features = ["sink"] } quinn = { version = "0.11", optional = true } diff --git a/scripts/check-advisories.py b/scripts/check-advisories.py index f47fb0987..bbeab3ebb 100755 --- a/scripts/check-advisories.py +++ b/scripts/check-advisories.py @@ -91,6 +91,31 @@ ALLOW = { # was removed outright rather than excused. "RUSTSEC-2023-0071": "rsa: no fixed release; verification only, no decryption, private keys test-only", # ── Pinned by a dependency; needs an upstream release ────────────────── + # zstd's four October 2026 advisories (a stream's data leaking into the + # next on a reused context; Seekable::decompress past the end; uninitialised + # memory from a failed legacy-frame stream; the wasm allocator shim). Every + # direct use here moved to zstd 0.14.3 / zstd-safe 8.2.0 / zstd-sys 2.1.2. + # The one copy left is wasmtime 49's: wasmtime-internal-cache compresses + # compiled modules for wasmtime's on-disk cache, and sandbox-exec-wasm + # builds its engine from Config::new() with fuel metering only and never + # configures a cache, so none of zstd's code runs in the sandbox. Pinned to + # those exact versions: a direct use regressing to them is not excused. + "RUSTSEC-2026-0391": { + "why": "zstd 0.13.3 only in wasmtime 49's module cache, which the sandbox never configures", + "only": ("zstd 0.13.3",), + }, + "RUSTSEC-2026-0398": { + "why": "zstd-safe 7.2.4 only under wasmtime 49's module cache, which the sandbox never configures", + "only": ("zstd-safe 7.2.4",), + }, + "RUSTSEC-2026-0403": { + "why": "zstd-safe 7.2.4 only under wasmtime 49's module cache, which the sandbox never configures", + "only": ("zstd-safe 7.2.4",), + }, + "RUSTSEC-2026-0410": { + "why": "zstd-sys 2.0.16 only under wasmtime 49's module cache, never configured, and native: the shim is wasm's", + "only": ("zstd-sys 2.0.16+zstd.1.5.7",), + }, # Secret-dependent branches in operations meant to be constant-time # (subtraction, zero counting, division, Montgomery multiplication), so # timing can leak intermediate arithmetic on a secret integer. Fixed in diff --git a/wai/wai-rs/Cargo.lock b/wai/wai-rs/Cargo.lock index 10e15f81d..5ac59f150 100644 --- a/wai/wai-rs/Cargo.lock +++ b/wai/wai-rs/Cargo.lock @@ -5252,27 +5252,27 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zstd" -version = "0.13.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +checksum = "db3ae9bf90af6e40197bef767eeefc46ad6397420fe873830bd85e5fbbfb3c70" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.4" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +checksum = "ded520f16b29e1a9b771c722221b2b0a0398c2316d9bb3c42b458a5414d7434b" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" +version = "2.1.2+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +checksum = "481ada9c543b2323cbb7bbdbb5249177fbf0188ed959ed2c15e4b22421c84ed3" dependencies = [ "cc", "pkg-config", diff --git a/wai/wai-rs/Cargo.toml b/wai/wai-rs/Cargo.toml index 9ad9b8fea..bd2527a2e 100644 --- a/wai/wai-rs/Cargo.toml +++ b/wai/wai-rs/Cargo.toml @@ -52,7 +52,7 @@ flac-bound = { version = "0.5", optional = true } # FLAC encode (libFLAC) rav1e = { version = "0.8", default-features = false, features = ["threading"], optional = true } dav1d = { version = "0.11", optional = true } # AV1 decode (libdav1d) # Text -zstd = { version = "0.13", optional = true } # zstd bindings +zstd = { version = "0.14.3", optional = true } # zstd bindings (0.14.3: RUSTSEC-2026-0391, -0398, -0403, -0410) xz2 = { version = "0.1", optional = true } # liblzma bindings (XZ/LZMA) # Bytestream framing for video container (we wrap rav1e packets into a @@ -73,7 +73,7 @@ ndarray = { version = "0.17", optional = true } # library or wasm32 build enables the feature. ring is the provider already in the graph. rustls = { version = "0.23", default-features = false, features = ["std", "ring", "tls12"], optional = true } rustls-platform-verifier = { version = "0.7", optional = true } -zstd-safe = { version = "7", optional = true, features = ["std"] } # for bmshj2018 latent unpack (std → WriteBuf for Vec) +zstd-safe = { version = "8.2", optional = true, features = ["std"] } # for bmshj2018 latent unpack (std → WriteBuf for Vec) # SHA-256 is WAI's digest for parameter-set identity, component identity and decoded-output # conformance digests (SPEC §3.1, §7 *Digests*, §7.1). Pure Rust, so it is always on: the # envelope reader verifies a component digest and a pin with no feature enabled. diff --git a/wai/wai-rs/fuzz/Cargo.lock b/wai/wai-rs/fuzz/Cargo.lock index 4a8beda59..f8e7611ae 100644 --- a/wai/wai-rs/fuzz/Cargo.lock +++ b/wai/wai-rs/fuzz/Cargo.lock @@ -1475,7 +1475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.3.4", "once_cell", "rustix", "windows-sys", @@ -1788,27 +1788,27 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zstd" -version = "0.13.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +checksum = "db3ae9bf90af6e40197bef767eeefc46ad6397420fe873830bd85e5fbbfb3c70" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.3.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d80649ab6db9d9f6f9c80a40becd948eda4714a0a5ac8c4d157a32231c7882" +checksum = "ded520f16b29e1a9b771c722221b2b0a0398c2316d9bb3c42b458a5414d7434b" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.1.1+zstd.1.5.7" +version = "2.1.2+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeec9eaf2dffbbd09201e23bd0ffcbaa33bb8e9266a10734fd7ed90a85eca078" +checksum = "481ada9c543b2323cbb7bbdbb5249177fbf0188ed959ed2c15e4b22421c84ed3" dependencies = [ "cc", "pkg-config", -- 2.54.0 (Apple Git-157) From cb88dd7fa1606b23a6f3dca66279944f1d29910e Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Mon, 26 Oct 2026 11:35:49 -0400 Subject: [PATCH 2/2] CI: the avx2 leg declares the units the runner's processor has The `linux` label now has two runners: jetson-hub, whose processor has avx2, and framework-128gb-linux (since 2026-10-26), whose processor has avx512 too. The avx2 leg declared avx2 alone, so on the framework the engine's probe found avx2 and avx512, the declaration did not match, and all nine device tests failed (#487's run, task 29781). On silicon the declaration now comes from the kernel's own flags (avx512f in /proc/cpuinfo), never from the probe under test, and the leg checks the avx2 member exactly as before: its 256-bit length, its four bit-exact certificates and its three killed mutants. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/wai-quantum-vector.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wai-quantum-vector.yml b/.github/workflows/wai-quantum-vector.yml index 50ad1cefa..906155fb2 100644 --- a/.github/workflows/wai-quantum-vector.yml +++ b/.github/workflows/wai-quantum-vector.yml @@ -4,7 +4,10 @@ name: wai-quantum CPU vector units # the processor's own vector extension, certified bit-exact against the CPU # reference's pinned corpus digests. # -# - avx2 on silicon: the container runner's x86-64 processor; +# - avx2 on silicon: the x86-64 processor of whichever `linux` runner takes +# the leg. jetson-hub's has avx2 alone; framework-128gb-linux's has avx512 +# too, and there the leg declares both, as the kernel reports them, and +# checks the avx2 member as on any other; # - avx2 and avx512 on silicon together: framework-128gb's processor, which has # both, one member each; # - sve and rvv under the host's user-mode emulator (its binfmt handler), at @@ -150,6 +153,11 @@ jobs: rustup target add ${{ matrix.target }} # The emulated processor, for the test binaries only. if [ -n "${{ matrix.qemu_cpu }}" ]; then export QEMU_CPU="${{ matrix.qemu_cpu }}"; fi + # Every unit this processor has must be declared, so on silicon the + # declaration comes from the kernel's own flags, not the probe under test. + if [ "${{ matrix.key }}" = cpu-vector-avx2 ] && grep -qw avx512f /proc/cpuinfo; then + export WAI_QUANTUM_VECTOR_EXPECT=cpu-vector-avx2,cpu-vector-avx512 + fi t="--target ${{ matrix.target }} --features quantum_fabric_vector" cargo test --locked --release -j 6 $t --lib -- quantum_fabric_vector:: 2>&1 | tee "$cache/unit.log" grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$cache/unit.log" || { echo "::error::no unit test ran"; exit 1; } @@ -157,8 +165,8 @@ jobs: WAI_QUANTUM_VECTOR_REPORT="$report" cargo test --locked --release -j 6 $t --test vector_member -- --test-threads=1 2>&1 | tee "$cache/device.log" grep -qE '^test result: ok\. 9 passed; 0 failed' "$cache/device.log" || { echo "::error::not every device test ran and passed"; exit 1; } cat "$report" - key="$WAI_QUANTUM_VECTOR_EXPECT" - grep -qx "vector devices: as declared ($key)" "$report" || { echo "::error::the unit found is not the declared one"; exit 1; } + key="${{ matrix.key }}" + grep -qx "vector devices: as declared ($WAI_QUANTUM_VECTOR_EXPECT)" "$report" || { echo "::error::the units found are not the declared ones"; exit 1; } grep -q "^vector member: key=$key .* bits=${{ matrix.bits }} " "$report" || { echo "::error::the unit's vector length is not ${{ matrix.bits }} bits"; exit 1; } if [ -n "$WAI_QUANTUM_VECTOR_EMULATOR" ]; then grep -q "^vector member: key=$key .*emulator:qemu-user" "$report" || { echo "::error::the member does not say it ran under the emulator"; exit 1; } -- 2.54.0 (Apple Git-157)