You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
The 8-byte WASM preamble is not covered by the signature (needs a signature-format version bump) #303
Found by the v0.12.0 pre-release Mythos pass. Deferred deliberately — the fix is format-breaking (see below), so it must not ride along in a patch.
Mechanism
Neither signing nor verification hashes Module::header (the 8-byte WASM preamble):
SecretKey::sign (verify-core/signature/simple.rs:32-79) hashes only section.serialize(..) output.
Module::init_from_reader consumes the preamble before hashing begins, so PublicKey::verify's hash starts after it.
init_from_reader (wasm_module/mod.rs:23-24, 418-425) accepts bothWASM_HEADER and WASM_COMPONENT_HEADER.
So a signed core module's preamble can be rewritten to the component preamble (or vice versa) and the signature still verifies. validate_format_consistency runs only at sign time (src/cli/main.rs:782), never on verify.
Consequence (scoped honestly)
The signature does not bind the artifact bytes — two distinct files share one valid signature, and the preamble is precisely what selects every WASM runtime's parse mode (core module vs component).
I make no claim that the relabelled file loads as a working malicious component; reparsing core sections under the component ID namespace would most likely fail validation, and that was not demonstrated. The defect is the integrity gap itself.
Adjacent to AS-17/UCA-16 (polyglot format confusion) but distinct — this is intra-WASM, same parser, no second file format.
Oracle
poc_verify_accepts_rewritten_module_preamble in verify-core/signature/simple.rs, currently #[ignore]d with a pointer to this issue. It has a positive control (untampered verifies) and a negative control (preamble byte 1 → 0xff ⇒ Err(UnsupportedModuleType), proving the preamble is not skipped unexamined). Mutation-checked during discovery: binding the preamble into the hash in both sign and verify flips it to pass.
Why it's deferred, not fixed in v0.12.0
Hashing the preamble changes what gets signed, so it invalidates every existing signature. That requires:
a signature-format version bump (SIGNATURE_VERSION),
a verifier that accepts both old and new forms during migration (or an explicit break), and
a ModuleStreamReader::header() accessor, i.e. a change in wasm_module/.
That is a deliberate, migration-bearing change — wrong to slip into a release whose scope is keyless/bundle interop.
Suggested fix
Bump SIGNATURE_VERSION, include the 8 preamble bytes at the front of the hashed stream in both sign and verify (all of simple/multi/matrix), and decide explicitly whether v1 signatures remain acceptable. Consider also running validate_format_consistency on the verify path.
Activity