From c409609c9911b6649d43d97159788ea4b2f1c1cb Mon Sep 17 00:00:00 2001 From: dyslexicsteak Date: Tue, 27 Oct 2026 18:29:48 +0800 Subject: [PATCH] Add entry for Wasmtime builtin composition vulnerability --- crates/wasmtime/RUSTSEC-0000-0000.md | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 crates/wasmtime/RUSTSEC-0000-0000.md diff --git a/crates/wasmtime/RUSTSEC-0000-0000.md b/crates/wasmtime/RUSTSEC-0000-0000.md new file mode 100644 index 0000000000..bf2f3be38d --- /dev/null +++ b/crates/wasmtime/RUSTSEC-0000-0000.md @@ -0,0 +1,82 @@ +```toml +[advisory] +id = "RUSTSEC-0000-0000" +package = "wasmtime" +date = "2026-10-27" +url = "https://github.com/bytecodealliance/wasmtime/issues/15024" +categories = ["code-execution", "denial-of-service", "format-injection", "memory-corruption", "memory-exposure", "privilege-escalation"] +cvss = "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H" + +[affected.functions] +"wasmtime::CodeBuilder::expose_unsafe_intrinsics" = [">= 39.0.0"] + +[versions] +patched = [] +unaffected = ["< 39.9.0"] +``` +# Compile-time builtin composition resolves guest imports from host working directory + +## Summary + +Wasmtime composes builtins through `wasm-compose`'s `ComponentComposer`, which +falls back to searching on disk in the current working directory to satisfy +guest-chosen imports by name for CLI purposes, treating any file found at the +imported name’s path as trusted (in the same privilege as embedder builtins). A +component found on disk by a guest-chosen import name, as a result, can import +Wasmtime's unsafe intrinsics, which are native unchecked memory accesses to host +addresses meant to be exposed to legitimate, trusted builtins. This results in +arbitrary R/W by untrusted code and potential code execution. This violates the +[documented principle](https://docs.rs/wasmtime/latest/wasmtime/struct.CodeBuilder.html#method.expose_unsafe_intrinsics) +of the guest not being part of the trusted compute base. + +## Details + +Code is referenced against +[ec63b69](https://github.com/bytecodealliance/wasmtime/commit/ec63b69f3da9783db784eef6ba67635385926a2a). + +The write process of Wasmtime's composition uses the filesystem as scratch +space, where +[`compile_time_builtins.rs` lines 23-43](https://github.com/bytecodealliance/wasmtime/blob/ec63b69f3da9783db784eef6ba67635385926a2a/crates/wasmtime/src/compile/code_builder/compile_time_builtins.rs#L39-43) +makes an import name into a path name verbatim and writes the builtin's bytes +to that path within a temporary directory with the shape +`/_deps/.wasm`. In the Wasm component model ecosystem, +interface names are conventionally shaped `ns:pkg/if@ver`, and by putting this +verbatim into the filesystem, the slash in the path allows for traversal, and +single letter namespaces resolve as drive letters on Windows. Versions with +dot-separated segments get their last segment chopped off on +[line 40](https://github.com/bytecodealliance/wasmtime/blob/ec63b69f3da9783db784eef6ba67635385926a2a/crates/wasmtime/src/compile/code_builder/compile_time_builtins.rs#L40) +by setting the extension to "wasm", making `ns:pkg/if@1.0.0` and +`ns:pkg/if@1.0.1` both become the filesystem path `/ns:pkg/if@1.0.wasm`, +potentially reverting a patch or obscuring its presence from other logic. The +colon in the path can also make it malformed on Windows, causing OS errors. + +The composition read process begins in +[`code_builder.rs` lines 203-216](https://github.com/bytecodealliance/wasmtime/blob/ec63b69f3da9783db784eef6ba67635385926a2a/crates/wasmtime/src/compile/code_builder.rs#L203-L216), +calling `compose_compile_time_builtins`. `compile_time_builtins.rs` then creates +a default `Config` with an empty `dir` at +[line 32](https://github.com/bytecodealliance/wasmtime/blob/ec63b69f3da9783db784eef6ba67635385926a2a/crates/wasmtime/src/compile/code_builder/compile_time_builtins.rs#L32), +then, +[lines 50-51](https://github.com/bytecodealliance/wasmtime/blob/ec63b69f3da9783db784eef6ba67635385926a2a/crates/wasmtime/src/compile/code_builder/compile_time_builtins.rs#L50-L51) +compose with `ComponentComposer`, triggering the search on disk at `composer.rs` +[lines 128-166](https://github.com/bytecodealliance/wasm-tools/blob/cc0d3b77653571c75791291df7fa0c32bbb9405a/crates/wasm-compose/src/composer.rs#L128-L166) +via `find_component` and `parse_component` that try `dir.join(name)` with +".wasm" and ".wat", searching the host's working directory. + +After composition, `translate.rs` lines +[934](https://github.com/bytecodealliance/wasmtime/blob/ec63b69f3da9783db784eef6ba67635385926a2a/crates/environ/src/component/translate.rs#L934) +and +[1810](https://github.com/bytecodealliance/wasmtime/blob/ec63b69f3da9783db784eef6ba67635385926a2a/crates/environ/src/component/translate.rs#L1810) +resolve the intrinsic import regardless of its provenance, and consequently, a +component found on disk this way is composed in alongside the embedder’s +builtins with the same standing, i.e. if it imports the Wasmtime intrinsics now +it receives the real ones. + +The Wasmtime unsafe intrinsics allow callers to arbitrarily read and write host +process memory and are meant to be used only by legitimate builtins explicitly +trusted by the embedder. By the mechanisms previously mentioned, an untrusted +guest can traverse paths, cause errors with them, or name any modules to import +with the same standing as compile-time builtins, giving them access to the +unsafe intrinsics and compromising the trusted compute base. + +PR [#15025](https://github.com/bytecodealliance/wasmtime/pull/15025) resolves +this by composing in-memory without using CLI machinery.