Skip to content

chore(deps): bump Rust to 1.94 and wasmtime to 46.0.2 (RUSTSEC-2026-0222) - #209

Merged
dshakes merged 2 commits into
masterfrom
chore/rust-1.94-wasmtime
Jul 31, 2026
Merged

dshakes merged 2 commits into
masterfrom
chore/rust-1.94-wasmtime

Conversation

@dshakes

@dshakes dshakes commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Closes the vuln gate, which is currently red on master.

Why one PR and not two

wasmtime 45.0.3 is affected by RUSTSEC-2026-0222 (Stores can mix up type indices between engines). Every patched line the advisory allows — 46.0.2+ and 47.0.3+ — pulls cranelift crates that require Rust 1.94. So the dependency fix does not compile without the toolchain move; neither half stands alone.

Changes

  • Toolchain 1.93 → 1.94.1 everywhere it is pinned: rust-toolchain.toml, two CI workflow pins (sdlc-lint, runtime-exec-e2e), and four service Dockerfiles. Confirmed rust:1.94-slim exists before relying on it — a missing tag would have broken every container build while local builds stayed green.
  • wasmtime 45.0.2 → 46.0.2 (+ wasmtime-wasi, release-synced). Chose the 46 line over 47: smaller step that clears the advisory, and it needed no source changes.
  • One new lint. 1.94 tightens clippy::result_large_err, which fires on the exec server's interceptor closure over tonic's 176-byte Status. Both halves of that signature are tonic's — Interceptor requires exactly FnMut(Request<()>) -> Result<Request<()>, Status> — so the error cannot be boxed without failing to implement the trait. Allowed with that reason, matching the identical allow already on validate_first_frame in the same file.

Verification (Rust 1.94.1, all five Rust services)

check result
clippy --all-targets -D warnings clean
rustfmt --check clean
cargo audit clean — 0221 and 0222 both gone
tests gateway 31 · model-router 38 · surface-gateway 63 · harness 155 · runtime-manager 350

Note on #208

This branches off fix/rustsec-2026-0221, so it includes the event-listener 5.4.2 bump — otherwise vuln could not go green here (it would still fail on the other advisory). Merging this makes #208 redundant; close it, or merge it first and this rebases cleanly.

dshakes added 2 commits July 31, 2026 16:32
`event-listener` 5.4.1 allows `!Send` tags to cross thread boundaries via
`StackSlot` (RUSTSEC-2026-0221, published 2026-07-13). It reaches the
runtime-manager transitively through async-broadcast, so this is a lockfile-only
change: no manifest edit, no API surface touched.

Turned up when the vuln gate went red on an unrelated PR — the advisory database
picked it up between this morning's runs and this afternoon's, so it now fails on
master too.

This clears RUSTSEC-2026-0221 only. `cargo audit` still reports RUSTSEC-2026-0222
(wasmtime 45.0.3, "Stores can mix up type indices between engines"), which is NOT
fixable the same way: every patched line the advisory allows — 46.0.2+ and
47.0.3+ — pulls cranelift crates requiring Rust 1.94, while the repo pins 1.93 in
rust-toolchain.toml, two CI workflows, and the service Dockerfiles. That is a
cross-cutting toolchain decision and gets its own change rather than riding along
here.

Verified: cargo audit no longer reports 0221, release build clean.
…222)

wasmtime 45.0.3 lets Stores mix up type indices between engines
(RUSTSEC-2026-0222). Every patched line the advisory allows — 46.0.2+ and
47.0.3+ — pulls cranelift crates requiring Rust 1.94, so the fix is not a
dependency bump on its own; the toolchain has to move with it. That is why this
lands as one change rather than two: neither half compiles without the other.

Toolchain 1.93 -> 1.94.1 in every place it is pinned: rust-toolchain.toml, the
two CI workflow pins (sdlc-lint, runtime-exec-e2e), and the four service
Dockerfiles. `rust:1.94-slim` was confirmed to exist before relying on it —
a missing tag would have broken every container build while the local builds
stayed green.

wasmtime 45.0.2 -> 46.0.2 (with wasmtime-wasi, which is release-synced). Chose
the 46 line over 47 because it is the smaller step that clears the advisory, and
it needed no source changes at all.

The one thing the new toolchain broke is a tightened `clippy::result_large_err`
on the exec server's interceptor closure, over tonic's 176-byte `Status`. Both
halves of that signature are tonic's: `Interceptor` requires exactly
`FnMut(Request<()>) -> Result<Request<()>, Status>`, so the error cannot be
boxed without failing to implement the trait. Allowed with that reason, matching
the identical allow already on `validate_first_frame` in the same file.

Verified on 1.94.1 across all five Rust services:
  clippy --all-targets -D warnings   clean
  rustfmt --check                    clean
  cargo audit                        clean — 0221 and 0222 both gone
  tests: gateway 31, model-router 38, surface-gateway 63, harness 155,
         runtime-manager 350

Includes the event-listener 5.4.2 bump (RUSTSEC-2026-0221) from the branch this
is based on, so the vuln gate can actually reach green here.
@github-actions github-actions Bot added the domain:infra Touches infra / CI / deploy / migrations label Jul 31, 2026
@compass-sdlc-bot compass-sdlc-bot Bot added the agent:reviewed-clean Reviewer found no Blocking issues this round label Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Codex cross-audit (agent:audit)

Blocking: none found.

Findings:

  • Low: rust-toolchain.toml now says services/*/Dockerfile use rust:1.94-slim, but services/harness/Dockerfile still builds with rust:1.85-alpine. This is not an immediate regression from the current hunk, but it leaves harness builds on a different compiler than CI/dev after this PR’s toolchain bump.

Verification limits: I could not run Cargo/rustc checks because the sandbox is read-only and rustup/rustc need temp/target writes. I did run git diff --check origin/master...HEAD, which passed.

@github-actions

Copy link
Copy Markdown
Contributor

🔷 Gemini cross-audit (agent:audit-gemini)

🚨 BLOCKING REGRESSION

1. Compilation Failure in services/runtime-manager/src/backends/wasm.rs

The PR upgrades wasmtime and wasmtime-wasi from version 45.0.2 to 46.0.2 in services/runtime-manager/Cargo.toml, but does not update the code to handle a major breaking change in wasmtime-wasi v46.0.

In Wasmtime v46.0.0, the temporary p2 module hierarchy was removed since WASIp2 features became stabilized at the root level of the crate. As a result:

  • The issue: The import of MemoryOutputPipe in services/runtime-manager/src/backends/wasm.rs (line 74) will cause a compilation error:
    use wasmtime_wasi::p2::pipe::MemoryOutputPipe; // unresolved import `wasmtime_wasi::p2`
  • The fix: Update the import statement in wasm.rs to point to the new top-level structure:
    use wasmtime_wasi::pipe::MemoryOutputPipe;
  • Additionally, the documentation comment at line 52 should be updated to refer to wasmtime_wasi::pipe::MemoryOutputPipe instead of wasmtime_wasi::p2::pipe::MemoryOutputPipe.

🔍 LINTING & WORKFLOW COVERAGE

2. Clippy result_large_err Check

The addition of #[allow(clippy::result_large_err)] in services/harness/src/exec.rs (line 589) is correct and necessary.
Under Rust 1.94, the size threshold for this lint was tightened, and tonic::Status (176 bytes) now triggers it inside any interceptor closure matching FnMut(Request<()>) -> Result<Request<()>, Status>.

  • Coverage Verification: We scanned all other Rust-based services (gateway, model-router, and surface-gateway) to verify if they used tonic interceptors. No other files define inline GRPC client or server interceptors returning Result<..., Status>, meaning this is the only location that requires the suppression attribute.

3. Musl Target & Harness Dockerfile Consistency

  • Observation: services/harness/Dockerfile was not modified and continues to build with rust:1.85-alpine.
  • Concurrence: This is correct and safe. The harness is a statically-linked PID 1 musl-static binary that runs inside the guest microVMs. It is decoupled from the host runtime-manager's Rust toolchain, and pinning it to an alpine-builder version prevents compatibility drifts in the microVM rootfs environment.

@dshakes dshakes added the agent:audit Auditor (Codex): independent cross-audit label Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔷 Gemini cross-audit (agent:audit-gemini)

Audit Findings for pr-diff.patch


🚨 BLOCKING: Compilation Failure

  • Issue: Upgrading wasmtime/wasmtime-wasi to 46.0.2 in services/runtime-manager/Cargo.toml without updating services/runtime-manager/src/backends/wasm.rs will fail to compile.
  • Details: In wasmtime-wasi v46, the p2 (preview2) submodule was fully promoted to the root of the crate. Therefore, use wasmtime_wasi::p2::pipe::MemoryOutputPipe; on line 77 of wasm.rs is no longer valid.
  • Fix: Update the import to use wasmtime_wasi::pipe::MemoryOutputPipe; and update corresponding comments (lines 35–40).

⚠️ HIGH: Missed Edge Case (Global Engine Epoch Ticking / Concurrency Bug)

  • Issue: Severe race condition resulting in premature/immediate timeouts under concurrent WebAssembly workloads.
  • Details: In services/runtime-manager/src/backends/wasm.rs, WasmBackend uses a single shared Engine instance. Every invocation of schedule() or schedule_and_stream() spawns a dedicated background task that sleeps 1s and calls engine_for_ticker.increment_epoch(). Under concurrent load (e.g., 20 concurrent workloads), 20 background tasks will concurrently increment the global engine's epoch. The global epoch will tick 20x faster, causing a 300s deadline (store.set_epoch_deadline(300)) to expire in just 15 seconds.
  • Fix: Instead of per-instance epoch ticking, run a single global ticker loop within WasmBackend that increments the global Engine epoch exactly once per second.

✅ CORRECTNESS: Bearer Token Clippy Suppression

  • Details: The addition of #[allow(clippy::result_large_err)] to the with_interceptor closure inside services/harness/src/exec.rs is correct and necessary. Rust 1.94 has tighter clippy checking for closure return types, flagging the 176-byte tonic::Status which is mandatory for the gRPC interceptor trait signature and cannot be boxed.

@github-actions

Copy link
Copy Markdown
Contributor

🔎 Codex cross-audit (agent:audit)

Blocking: none found.

I did not find additional correctness or security regressions in git diff origin/master...HEAD. The PR delta is limited to Rust toolchain/image version bumps, Wasmtime/WASI dependency bump for runtime-manager, and a targeted Clippy allow on the harness tonic interceptor.

Verification notes:

  • cargo metadata --locked --offline --no-deps succeeded for services/runtime-manager.
  • Full cargo check/tests could not run because the environment is read-only and rustup/cargo need to write toolchain/target files.
  • Residual risk is the Wasmtime 45 -> 46 sandbox-path upgrade; CI should run cargo test/clippy for runtime-manager before merge.

@dshakes
dshakes merged commit 03cdf73 into master Jul 31, 2026
26 checks passed
@dshakes
dshakes deleted the chore/rust-1.94-wasmtime branch July 31, 2026 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:audit Auditor (Codex): independent cross-audit agent:reviewed-clean Reviewer found no Blocking issues this round domain:infra Touches infra / CI / deploy / migrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant