Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR 0037: Wasmtime CVE risk register

Status: Accepted Date: 2026-07-23 Issue: #463

Context

Arbitraitor uses Wasmtime as its primary plugin runtime (ADR-0006). The arbitraitor-plugin-host crate depends on wasmtime with default-features = false and the cranelift, runtime, component-model, parallel-compilation, and cache features. The experimental-wasm feature gate is off by default. The resolved version in Cargo.lock is wasmtime 46.0.1.

On 2026-04-09 the Bytecode Alliance published a batch of 12 security advisories for Wasmtime. Two are Critical (CVSS 9.0):

  • CVE-2026-34971 / GHSA-jhxm-h53p-jm7w — Cranelift aarch64 miscompilation enabling sandbox escape via arbitrary host-memory read/write.
  • CVE-2026-34987 / GHSA-xx5w-cvp6-jv83 — Winch compiler backend sandbox-escaping memory access on aarch64.

Both allow a malicious WebAssembly guest module to read or write arbitrary host memory, defeating the sandbox boundary that ADR-0006 relies on for plugin isolation. Spec §41.9.1 governs Wasmtime plugin execution but has no risk register tying compiler/backend selection and version to security guarantees.

This ADR establishes that risk register as a versioned, living document.

Decision

Adopt a versioned Wasmtime CVE risk register cataloging all known advisories from official sources (GitHub Security Advisories, RustSec, NVD/CVE). The register is maintained in this ADR and updated whenever a new Wasmtime advisory is published or the pinned version changes.

Pinned version

FieldValue
Cratewasmtime
Cargo.toml constraint>=29
Resolved version (Cargo.lock)46.0.1
Features enabledcranelift, runtime, component-model, parallel-compilation, cache
Features disabled (default-features = false)WASI, ambient filesystem, networking, all ambient capabilities
Feature gateexperimental-wasm (off by default)
Minimum safe version (per issue #463)43.0.1

Risk register

All advisories below are sourced from the Bytecode Alliance GitHub Security Advisories page (https://github.com/bytecodealliance/wasmtime/security/advisories) and the RustSec advisory database (https://rustsec.org/advisories/). The “Affected?” column reflects whether the pinned version 46.0.1 is vulnerable.

Critical

CVE / GHSA / RUSTSECSeverityAffected versionsFixedDescriptionAffected?
CVE-2026-34971 / GHSA-jhxm-h53p-jm7w / RUSTSEC-2026-0096Critical (9.0)>=32.0.0, <36.0.7; >=37.0.0, <42.0.2; >=43.0.0, <43.0.136.0.7, 42.0.2, 43.0.1Cranelift aarch64 miscompiles load(iadd(base, ishl(index, amt))) when wasm_memory64 is enabled and Spectre mitigations are disabled, creating divergent bounds-check vs. load addresses. Enables arbitrary host-memory read/write (sandbox escape).No — 46.0.1 >= 43.0.1
CVE-2026-34987 / GHSA-xx5w-cvp6-jv83 / RUSTSEC-2026-0095Critical (9.0)>=25.0.0, <36.0.7; >=37.0.0, <42.0.2; >=43.0.0, <43.0.136.0.7, 42.0.2, 43.0.1Winch compiler backend assumes upper bits of a 32-bit memory offset stored in a 64-bit register are cleared when they may not be. Allows guest Wasm to access memory before/after the linear-memory sandbox. Observed PoC on aarch64; x86-64 theoretical.No — 46.0.1 >= 43.0.1, and Winch is not enabled

High

CVE / GHSA / RUSTSECSeverityAffected versionsFixedDescriptionAffected?
GHSA-2r75-cxrj-cmph / RUSTSEC-2026-0149High (7.5)wasmtime-wasi <24.0.9; >=36.0.10, <37.0.0; >=44.0.2, <45.0.0; <46.0.024.0.9, 36.0.10, 44.0.2, 46.0.0WASI path_open(TRUNCATE) bypasses FilePerms::WRITE host restriction.Nowasmtime-wasi not in dependency tree (default-features = false)

Moderate

CVE / GHSA / RUSTSECSeverityAffected versionsFixedDescriptionAffected?
CVE-2026-34941 / GHSA-hx6p-xpx3-jvvv / RUSTSEC-2026-0093Moderate (6.9)<24.0.7; >=36.0.7, <37.0.0; >=42.0.2, <43.0.0; <43.0.124.0.7, 36.0.7, 42.0.2, 43.0.1Heap OOB read in component model UTF-16 to latin1+utf16 string transcoding.No — 46.0.1 >= 43.0.1
GHSA-394w-hwhg-8vgm / RUSTSEC-2026-0091Moderate (6.1)<24.0.7; >=36.0.7, <37.0.0; >=42.0.2, <43.0.0; <43.0.124.0.7, 36.0.7, 42.0.2, 43.0.1OOB write or crash when transcoding component model strings.No — 46.0.1 >= 43.0.1
GHSA-q49f-xg75-m9xw / RUSTSEC-2026-0089Moderate<43.0.143.0.1Host panic when Winch compiler executes table.fill.No — 46.0.1 >= 43.0.1, and Winch is not enabled
GHSA-qqfj-4vcm-26hvModerate<43.0.143.0.1Segfault or unused out-of-sandbox load with f64x2.splat on Cranelift x86-64.No — 46.0.1 >= 43.0.1
GHSA-f984-pcp8-v2p7 / RUSTSEC-2026-0094Moderate<43.0.143.0.1Improperly masked return value from table.grow with Winch compiler backend.No — 46.0.1 >= 43.0.1, and Winch is not enabled
GHSA-jxhv-7h78-9775 / RUSTSEC-2026-0092Moderate<43.0.143.0.1Panic when transcoding misaligned component model UTF-16 strings.No — 46.0.1 >= 43.0.1
GHSA-m758-wjhj-p3jqModerate<43.0.143.0.1Panic when lifting flags component value.No — 46.0.1 >= 43.0.1
GHSA-p8xm-42r7-89xgModerate<43.0.143.0.1Panic when allocating a table exceeding the size of the host’s address space.No — 46.0.1 >= 43.0.1
GHSA-243v-98vx-264hModerate<41.0.441.0.4Panic adding excessive fields to a wasi:http/types.fields instance.No — 46.0.1 >= 41.0.4
GHSA-xjhv-v822-pf94 / RUSTSEC-2026-0022Moderate (6.9)>=39.0.0, <40.0.4; >=40.0.4, <41.0.040.0.4, 41.0.4Panic when dropping a [Typed]Func::call_async future.No — 46.0.1 >= 41.0.4
GHSA-852m-cvvp-9p4w / RUSTSEC-2026-0020Moderate (6.9)<24.0.6; >=36.0.6, <37.0.0; >=40.0.4, <41.0.024.0.6, 36.0.6, 40.0.4, 41.0.4Guest-controlled resource exhaustion in WASI implementations.No — 46.0.1 >= 41.0.4
GHSA-vc8c-j3xm-xj73Moderate<25.0.025.0.0Segfault or unused out-of-sandbox load with f64.copysign on x86-64.No — 46.0.1 >= 25.0.0
GHSA-4ch3-9j33-3pmjModeratewasmtime-wasi <46.0.046.0.0WASI hard links and renames bypass FilePerms for destination.Nowasmtime-wasi not in dependency tree

Low

CVE / GHSA / RUSTSECSeverityAffected versionsFixedDescriptionAffected?
GHSA-hfr4-7c6c-48w2 / RUSTSEC-2026-0090Low (1.0)<43.0.043.0.1Use-after-free bug after cloning wasmtime::Linker.No — 46.0.1 >= 43.0.1
GHSA-6wgr-89rj-399p / RUSTSEC-2026-0088Low (2.3)<43.0.143.0.1Data leakage between pooling allocator instances.No — 46.0.1 >= 43.0.1, and pooling allocator is not enabled
GHSA-m9w2-8782-2946Low<43.0.143.0.1Host data leakage with 64-bit tables and Winch.No — 46.0.1 >= 43.0.1, and Winch is not enabled
GHSA-3p27-qvp9-27qfLowwasmtime-wasi <46.0.046.0.0Leak in WASIp1 fd_renumber implementation.Nowasmtime-wasi not in dependency tree

Historical

CVE / GHSA / RUSTSECSeverityAffected versionsFixedDescriptionAffected?
CVE-2024-47763 / GHSA-q8hx-mm92-4wvg / RUSTSEC-2024-0440High (5.5)<21.0.2; >=21.0.2, <22.0.0; >=22.0.1, <23.0.0; >=23.0.3, <24.0.0; >=24.0.1, <25.0.025.0.2Runtime crash when combining tail calls with stack traces.No — 46.0.1 >= 25.0.2

Exploitability assessment

Both Critical CVEs require a malicious WebAssembly guest module to be loaded and executed. The attack surface is:

  1. A plugin author crafts a .wasm component that exploits the Cranelift aarch64 miscompilation or the Winch backend memory access bug.
  2. The malicious component is loaded by arbitraitor-plugin-host.
  3. The component executes and reads/writes host memory outside the sandbox.

Mitigating factors in the current configuration:

  • The experimental-wasm feature is off by default. Wasmtime plugin loading is not active unless the feature is explicitly enabled at build time.
  • The Winch compiler backend is not enabled. Only cranelift is in the feature set, so CVE-2026-34987 (Winch-only) is not reachable.
  • CVE-2026-34971 requires wasm_memory64 enabled and Spectre mitigations disabled. Wasmtime enables Spectre mitigations by default; Arbitraitor does not disable them.
  • The pinned version 46.0.1 is above the fix version 43.0.1 for all April 2026 advisories.

Enforcement

  1. cargo-deny advisories checkdeny.toml already configures the RustSec advisory database (https://github.com/rustsec/advisory-db) and yanked = "deny". The security.yml CI workflow runs cargo deny check advisories on every PR. Any new Wasmtime advisory published to RustSec will automatically fail CI if the pinned version is affected.

  2. cargo-audit — The security.yml CI workflow also runs cargo audit as a second independent check against the RustSec database.

  3. GitHub dependency review — Blocks vulnerable dependency additions in PRs via GitHub’s native dependency review API.

  4. Monitoring process — The risk register in this ADR must be updated whenever:

Consequences

  • The risk register provides a single source of truth for Wasmtime CVE awareness in the Arbitraitor plugin sandbox.
  • cargo-deny and cargo-audit in CI automatically enforce the advisory baseline. No manual rule is needed in deny.toml for Wasmtime — the global advisories check covers it.
  • The >=29 version constraint in Cargo.toml is deliberately loose to allow Cargo to resolve to the latest compatible version. The lockfile pins 46.0.1, which is above all known fix versions. Lockfile changes are security-relevant per conventions §Dependencies and must be reviewed.
  • If a future advisory affects 46.0.1, CI will fail on the advisories check, blocking merge until the version is bumped or the advisory is formally evaluated and ignored with justification (following the pattern used for RUSTSEC-2025-0141 etc. in deny.toml).
  • Enabling the Winch compiler backend or wasm_memory64 in the future requires updating this risk register and re-evaluating exploitability.
  • The experimental-wasm feature gate means Wasmtime plugin loading is not active in default builds. The risk register still applies because the feature can be enabled by users building from source.

Alternatives considered

Pin a minimum version floor in Cargo.toml

Rejected for this PR. Tightening the wasmtime version constraint (e.g., >=43.0.1) is a separate decision that requires its own ADR and advisory check, per the issue #463 constraints. The risk register documents the minimum safe version; the actual version bump is tracked separately.

Add explicit ignore rules in deny.toml for wasmtime advisories

Rejected. The global cargo deny check advisories already catches affected versions. Adding ignore rules would suppress real findings. The existing ignore list is reserved for advisories that have been formally evaluated and accepted (e.g., transitive bincode via yara-x).

Build a custom CI job that scrapes the GHSA page

Rejected. The RustSec advisory database is already mirrored to ~/.cargo/advisory-dbs by cargo-deny and is the canonical source for Rust crate advisories. Building a separate scraper would duplicate existing infrastructure and add maintenance burden.

Catalog only the two Critical CVEs from the issue

Rejected. A risk register that only lists the two CVEs named in the issue would miss the 10 other advisories published in the same April 2026 batch, several of which are Moderate severity and relevant to the component-model and Cranelift features that Arbitraitor enables. A complete catalog is necessary for informed risk decisions.

References