John-Park-git opened issue #14014:
Test Case
Any module reproduces this — the panic happens while the CLI reads the host environment,
before the guest is instantiated. A do-nothing module is enough:(module (func (export "_start")) )Attached
noop-wasm-testcase.zipcontains that module compiled (noop.wasm, 36 bytes),
plus a bare(module)with no exports at all (empty.wasm, 8 bytes) which aborts the same
way. (Zipped for upload.)Steps to Reproduce
Unpack
noop.wasmfrom the attached zip (or build the module above with
wasm-tools parse).Put a single byte that is not valid UTF-8 into the environment and enable
inherit-env:
bash env BADV=$'\xff' wasmtime -S inherit-env noop.wasm
$'\xff'is bash syntax for one raw0xFFbyte. On Linux environment variables are byte
strings, so this is a legal host state, not a malformed one.Expected Results
Any of:
- the offending entry is skipped, or
- its bytes are passed through where the ABI allows it, or
- the command exits with a diagnostic.
The third option is what the
--envpath already does with the same input:$ wasmtime --env BADV=$'\xff' noop.wasm error: invalid UTF-8 was detected in one or more arguments $ echo $? 2Actual Results
Panic and abort:
thread 'main' (1234) panicked at /rustc/<hash>/library/std/src/env.rs:162:83: called `Result::unwrap()` on an `Err` value: "\xFF" note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Aborted (core dumped)Exit code 134 (SIGABRT).
Control cases with the same host environment, isolating the trigger to
inherit-env+ non-UTF-8:
Command Exit Result env BADV=$'\xff' wasmtime -S inherit-env noop.wasm134 panic / SIGABRT env BADV=$'\xff' wasmtime -S inherit-env=n noop.wasm0 ok env BADV=$'\xff' wasmtime noop.wasm0 ok env BADV=hello wasmtime -S inherit-env noop.wasm0 ok wasmtime --env BADV=$'\xff' noop.wasm2 clean diagnostic One invalid byte anywhere is enough, in the value or in the name. All of these abort:
env BADV=$'\xff' wasmtime -S inherit-env noop.wasm # exit 134 env BADV=$'A\xff' wasmtime -S inherit-env noop.wasm # exit 134 env BADV=$'\x80' wasmtime -S inherit-env noop.wasm # exit 134, orphan continuation byte env BADV=$'\xc3' wasmtime -S inherit-env noop.wasm # exit 134, truncated sequence env $'BAD\xffNAME=x' wasmtime -S inherit-env noop.wasm # exit 134, invalid byte in the nameValid UTF-8, including non-ASCII, is fine.
--wasi inherit-envand--wasi=inherit-env
behave the same as-S inherit-env.The guest ABI does not matter: a wasip1 module and a wasip2 component abort identically.
Versions and Environment
Wasmtime version or commit: 47.0.2 (90fed3c6a 2026-07-21), also reproduced on 46.0.1
(823d1b8f2)Operating system: Linux (Ubuntu 22.04)
Architecture: x86_64
Extra Info
I read the security policy first and am filing this publicly: the panic happens before the
guest is instantiated, so it is not a denial of service while executing Wasm, and
triggering it requires control over the host environment of the Wasmtime process. Happy to
move it to an advisory if you classify it differently.Cause.
std::env::vars()yields(String, String)and unwrapsinto_string()on each
entry, so any non-UTF-8 entry panics. On v47.0.2 there is a single call site,
src/common.rs:325-329inRunCommon::configure_wasip2:if self.common.wasi.inherit_env == Some(true) { for (k, v) in std::env::vars() { // <- panics on non-UTF-8 builder.env(&k, &v); } }Despite the name, the core-module path goes through the same function —
src/commands/run.rs:1350:self.run.configure_wasip2(&mut builder)?; let mut ctx = builder.build_p1();which is why a wasip1 module aborts as well.
Suggested fix. Iterate with
std::env::vars_os()and decide explicitly what to do with
entries that failinto_string(). The rejection policy already exists and is implemented
on the--envpath; it is simply not applied here.Not an ABI limitation. wasip2's
get-environmentreturns
list<tuple<string, string>>, so a component genuinely cannot receive non-UTF-8 — but the
abort also happens with a wasip1 module, whereenviron_getis byte-oriented, because the
panic precedes the guest ABI entirely. For reference, under the same input WAMR 2.4.5 and
WasmEdge 0.17.1 deliver the raw bytes to the guest unchanged (the guest receives
56 ff 57forV\xffW).Related but distinct. #4954 asks for non-UTF-8 command-line arguments to be accepted
rather than rejected. This report is not about relaxing that policy — it is that the
inherit-envpath aborts instead of applying it.Wasmer 7.2.0 panics the same way on its
--forward-host-envpath; reporting that
separately.Found while fuzzing WASI runtime CLI option handling for a research project.
John-Park-git added the bug label to Issue #14014.
alexcrichton closed issue #14014:
Test Case
Any module reproduces this — the panic happens while the CLI reads the host environment,
before the guest is instantiated. A do-nothing module is enough:(module (func (export "_start")) )Attached
noop-wasm-testcase.zipcontains that module compiled (noop.wasm, 36 bytes),
plus a bare(module)with no exports at all (empty.wasm, 8 bytes) which aborts the same
way. (Zipped for upload.)Steps to Reproduce
Unpack
noop.wasmfrom the attached zip (or build the module above with
wasm-tools parse).Put a single byte that is not valid UTF-8 into the environment and enable
inherit-env:
bash env BADV=$'\xff' wasmtime -S inherit-env noop.wasm
$'\xff'is bash syntax for one raw0xFFbyte. On Linux environment variables are byte
strings, so this is a legal host state, not a malformed one.Expected Results
Any of:
- the offending entry is skipped, or
- its bytes are passed through where the ABI allows it, or
- the command exits with a diagnostic.
The third option is what the
--envpath already does with the same input:$ wasmtime --env BADV=$'\xff' noop.wasm error: invalid UTF-8 was detected in one or more arguments $ echo $? 2Actual Results
Panic and abort:
thread 'main' (1234) panicked at /rustc/<hash>/library/std/src/env.rs:162:83: called `Result::unwrap()` on an `Err` value: "\xFF" note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Aborted (core dumped)Exit code 134 (SIGABRT).
Control cases with the same host environment, isolating the trigger to
inherit-env+ non-UTF-8:
Command Exit Result env BADV=$'\xff' wasmtime -S inherit-env noop.wasm134 panic / SIGABRT env BADV=$'\xff' wasmtime -S inherit-env=n noop.wasm0 ok env BADV=$'\xff' wasmtime noop.wasm0 ok env BADV=hello wasmtime -S inherit-env noop.wasm0 ok wasmtime --env BADV=$'\xff' noop.wasm2 clean diagnostic One invalid byte anywhere is enough, in the value or in the name. All of these abort:
env BADV=$'\xff' wasmtime -S inherit-env noop.wasm # exit 134 env BADV=$'A\xff' wasmtime -S inherit-env noop.wasm # exit 134 env BADV=$'\x80' wasmtime -S inherit-env noop.wasm # exit 134, orphan continuation byte env BADV=$'\xc3' wasmtime -S inherit-env noop.wasm # exit 134, truncated sequence env $'BAD\xffNAME=x' wasmtime -S inherit-env noop.wasm # exit 134, invalid byte in the nameValid UTF-8, including non-ASCII, is fine.
--wasi inherit-envand--wasi=inherit-env
behave the same as-S inherit-env.The guest ABI does not matter: a wasip1 module and a wasip2 component abort identically.
Versions and Environment
Wasmtime version or commit: 47.0.2 (90fed3c6a 2026-07-21), also reproduced on 46.0.1
(823d1b8f2)Operating system: Linux (Ubuntu 22.04)
Architecture: x86_64
Extra Info
I read the security policy first and am filing this publicly: the panic happens before the
guest is instantiated, so it is not a denial of service while executing Wasm, and
triggering it requires control over the host environment of the Wasmtime process. Happy to
move it to an advisory if you classify it differently.Cause.
std::env::vars()yields(String, String)and unwrapsinto_string()on each
entry, so any non-UTF-8 entry panics. On v47.0.2 there is a single call site,
src/common.rs:325-329inRunCommon::configure_wasip2:if self.common.wasi.inherit_env == Some(true) { for (k, v) in std::env::vars() { // <- panics on non-UTF-8 builder.env(&k, &v); } }Despite the name, the core-module path goes through the same function —
src/commands/run.rs:1350:self.run.configure_wasip2(&mut builder)?; let mut ctx = builder.build_p1();which is why a wasip1 module aborts as well.
Suggested fix. Iterate with
std::env::vars_os()and decide explicitly what to do with
entries that failinto_string(). The rejection policy already exists and is implemented
on the--envpath; it is simply not applied here.Not an ABI limitation. wasip2's
get-environmentreturns
list<tuple<string, string>>, so a component genuinely cannot receive non-UTF-8 — but the
abort also happens with a wasip1 module, whereenviron_getis byte-oriented, because the
panic precedes the guest ABI entirely. For reference, under the same input WAMR 2.4.5 and
WasmEdge 0.17.1 deliver the raw bytes to the guest unchanged (the guest receives
56 ff 57forV\xffW).Related but distinct. #4954 asks for non-UTF-8 command-line arguments to be accepted
rather than rejected. This report is not about relaxing that policy — it is that the
inherit-envpath aborts instead of applying it.Wasmer 7.2.0 panics the same way on its
--forward-host-envpath; reporting that
separately.Found while fuzzing WASI runtime CLI option handling for a research project.
Last updated: Aug 30 2026 at 10:08 UTC