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 49.0.1 (direct dependency; a second, transitive copy at 45.0.3 is pinned by yara-x 1.20.0).

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>=47.0.4 (security floor, ADR-0040)
Resolved version (Cargo.lock)49.0.1
Transitive yara-x copy45.0.3 (yara-x 1.20.0 requires wasmtime ^45.0.3; RUSTSEC-2026-0222/0269/0316 ignored with rationale)
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 version47.0.4 (per RUSTSEC-2026-0268/0269 fix ranges)

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 versions (49.0.1 direct, 45.0.3 yara-x-pinned transitive) are 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 — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 43.0.1, and Winch is not enabled

High

CVE / GHSA / RUSTSECSeverityAffected versionsFixedDescriptionAffected?
GHSA-vqjp-4c8c-hfgg / RUSTSEC-2026-0269High (8.8)<24.0.13; >=25.0.0, <36.0.14; >=37.0.0, <46.0.3; >=47.0.0, <47.0.424.0.13, 36.0.14, 46.0.3, 47.0.4Filesystem sandbox escape when paths or symlinks contain trailing slashes.Direct copy: No — resolved 49.0.1. Transitive yara-x copy (45.0.3): Yes — ignored in deny.toml with rationale (no patched yara-x release; formal evaluation in ADR-0040).
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.No — wasmtime-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 — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 43.0.1
GHSA-q49f-xg75-m9xw / RUSTSEC-2026-0089Moderate<43.0.143.0.1Host panic when Winch compiler executes table.fill.No — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 43.0.1
GHSA-m758-wjhj-p3jqModerate<43.0.143.0.1Panic when lifting flags component value.No — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 43.0.1
GHSA-243v-98vx-264hModerate<41.0.441.0.4Panic adding excessive fields to a wasi:http/types.fields instance.No — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 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 — direct 49.0.1 / transitive 45.0.3 — both >= 25.0.0
GHSA-4ch3-9j33-3pmjModeratewasmtime-wasi <46.0.046.0.0WASI hard links and renames bypass FilePerms for destination.No — wasmtime-wasi not in dependency tree
GHSA-x84v-gj2h-g759 / RUSTSEC-2026-0268Moderate (6.9)>=46.0.0, <46.0.3; >=47.0.0, <47.0.446.0.3, 47.0.4Guest controlled-size host heap allocation through WASIp3 streams.No — direct copy 49.0.1 >= 47.0.4; transitive copy 45.0.3 < 46.0.0 (advisory lists <46.0.0 as unaffected)

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 — direct 49.0.1 / transitive 45.0.3 — both >= 43.0.1
GHSA-6wgr-89rj-399p / RUSTSEC-2026-0088Low (2.3)<43.0.143.0.1Data leakage between pooling allocator instances.No — direct 49.0.1 / transitive 45.0.3 — both >= 43.0.1, and pooling allocator is not enabled
GHSA-m9w2-8782-2946 / RUSTSEC-2026-0086Low<43.0.143.0.1Host data leakage with 64-bit tables and Winch.No — direct 49.0.1 / transitive 45.0.3 — both >= 43.0.1, and Winch is not enabled
GHSA-hgjw-h833-99q9 / RUSTSEC-2026-0222Low (3.8)<24.0.12; >=25.0.0, <36.0.13; >=37.0.0, <46.0.2; >=47.0.0, <47.0.324.0.12, 36.0.13, 46.0.2, 47.0.3Stores can mix up type indices between engines.Direct copy: No — resolved 49.0.1. Transitive yara-x copy (45.0.3): Yes — ignored in deny.toml with rationale (evaluation in ADR-0040).
GHSA-3p27-qvp9-27qfLowwasmtime-wasi <46.0.046.0.0Leak in WASIp1 fd_renumber implementation.No — wasmtime-wasi not in dependency tree
GHSA-jqpg-j7w6-42pr / RUSTSEC-2026-0316Low<36.0.16; >=37.0.0, <48.0.3; >=49.0.0, <49.0.136.0.16, 48.0.3, 49.0.1Dynamic record lifting can allocate beyond the hostcall fuel limit.Direct copy: No — resolved 49.0.1. Transitive yara-x copy (45.0.3): Yes — ignored in deny.toml with rationale (no patched 45.x exists — fixes are in >=36.0.16, >=48.0.3, >=49.0.1; evaluation in ADR-0040, high-severity sibling RUSTSEC-2026-0269 handled the same way).

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 — direct 49.0.1 / transitive 45.0.3 — both >= 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 resolved versions are above the fix version for all April 2026 and August 2026 advisories (the direct copy at 49.0.1 is above all known fix versions; the yara-x transitive copy at 45.0.3 has formally-evaluated ignores for the three advisories it trips).

Enforcement

  1. cargo-deny advisories check — deny.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. The only Wasmtime entries in the deny.toml ignore list (RUSTSEC-2026-0222, RUSTSEC-2026-0269, RUSTSEC-2026-0316) are scoped to the transitive yara-x-pinned copy (45.0.3) and carry recorded removal conditions (ADR-0040) — all three drop when yara-x requires a patched wasmtime; every advisory against the direct dependency copy still fails CI.
  • The >=47.0.4 version constraint in Cargo.toml is a security floor (ADR-0040), not a pin: it states the minimum patched version while leaving semver-compatible upgrades to dependency tooling. The lockfile resolves 49.0.1 for the direct dependency, which is above all known fix versions (the yara-x-pinned transitive copy remains at 45.0.3 and is covered by the ignore rationale above). Lockfile changes are security-relevant per conventions §Dependencies and must be reviewed.
  • If a future advisory affects 49.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

Deferred at the time of this ADR (issue #463 constraints: a separate decision requiring its own ADR and advisory check); adopted by ADR 0040 in September 2026 after RUSTSEC-2026-0268/0269 affected the resolved version and fresh resolves could unify the direct copy onto yara-x’s then-required wasmtime ^43.0.2 range (yara-x 1.20.0 has since moved to ^45.0.3). The floor is now >=47.0.4.

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