{"record":{"id":"722e73871b2c6111","repo":"unionlabs/union","slug":"not-implemented-722e73","errorCode":null,"errorMessage":"not implemented","messagePattern":"not implemented","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/embed-commit/verifier/src/lib.rs","lineNumber":59,"sourceCode":"\n/// Retrieve the git rev from the provided wasm binary bytes.\n///\n/// # Errors\n///\n/// This function will error if the wasm binary bytes provided cannot be parsed, or if the returned git rev cannot be parsed. If there is no `commit_hash` export then `Ok(None)` will be returned.\npub fn extract_wasm(bz: &[u8]) -> Result<Option<Rev>> {\n    let engine = Engine::default();\n    let module = Module::from_binary(&engine, bz)?;\n    let mut linker = Linker::new(&engine);\n    let mut store: Store<()> = Store::new(&engine, ());\n\n    // stub all imports as they're unused when evaluating commit_hash\n    for import in module.imports() {\n        linker.func_new(\n            import.module(),\n            import.name(),\n            import.ty().unwrap_func().clone(),\n            |_, _, _| unimplemented!(),\n        )?;\n    }\n\n    let instance = linker.instantiate(&mut store, &module)?;\n\n    let Ok(commit_hash_fn) = instance.get_typed_func::<i32, ()>(&mut store, \"commit_hash\") else {\n        return Ok(None);\n    };\n\n    commit_hash_fn.call(&mut store, 0)?;\n\n    let memory = instance\n        .get_memory(&mut store, \"memory\")\n        .context(\"reading memory export\")?;\n\n    bytemuck::checked::try_from_bytes::<Rev>(&memory.data(&store)[0..std::mem::size_of::<Rev>()])\n        .map_err(|e| anyhow!(e.to_string()))\n        .context(\"parsing rev\")","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/unionlabs/union/blob/031785bb6dc6b957c624e62bc64c184409c97d7b/lib/embed-commit/verifier/src/lib.rs#L41-L77","documentation":"extract_wasm statically instantiates the target module under wasmer, stubbing every imported function with a host closure whose body is unimplemented!(). The assumption is that commit_hash (emitted by the embed-commit crate as a pure function that only writes its 32-byte Rev return value to linear memory) never calls imports. If a verified module's commit_hash does call an import, the stub panics, surfacing as a trap/runtime error from commit_hash_fn.call.","triggerScenarios":"Verifying a wasm that exports commit_hash but whose body calls an imported function — i.e., a binary not produced by the union embed-commit toolchain, or a toolchain revision where commit_hash got linked against imports.","commonSituations":"Feeding arbitrary third-party wasm into the verifier; producer and verifier built from different embed-commit versions; post-processing tools that rewrite the module and introduce import calls.","solutions":["Only run the verifier over artifacts built by the union embed-commit toolchain","Change the stub to return an Err (or wrap the call in catch_unwind) so a foreign module yields a typed 'not an embed-commit binary' result instead of a panic","Keep producer and verifier embed-commit crate versions in lockstep","Where possible, pre-check for a producer marker (e.g., a custom section) before executing the module"],"exampleFix":"// before\nfor import in module.imports() {\n  linker.func_new(import.module(), import.name(), import.ty().unwrap_func().clone(), |_, _, _| unimplemented!())?;\n}\n\n// after — surface a typed error instead of panicking when an import is reached\nfor import in module.imports() {\n  linker.func_new(\n    import.module(), import.name(), import.ty().unwrap_func().clone(),\n    |_, _, _| Err(wasmer::RuntimeError::new(\"import called while evaluating commit_hash; not an embed-commit module\")),\n  )?;\n}","handlingStrategy":"try-catch","validationCode":"// Cheap structural pre-check: only modules with a commit_hash export are candidates\nlet hasCommitHash = false\nfor (const exp of module.exports()) {\n  if (exp.name() === \"commit_hash\") hasCommitHash = true\n}\nif (!hasCommitHash) return Ok(None)","typeGuard":null,"tryCatchPattern":"// Keep the host alive if a foreign module calls a stubbed import\nlet outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    commit_hash_fn.call(&mut store, 0)\n}));\nmatch outcome {\n    Ok(Ok(())) => { /* read memory[0..32] as Rev */ }\n    Ok(Err(_trap)) | Err(_panic) => {\n        // commit_hash called an import or trapped: not an embed-commit module\n        return Ok(None);\n    }\n}","preventionTips":["Only verify artifacts produced by the union embed-commit toolchain","Run verification in a subprocess or catch_unwind boundary so panics cannot kill the host","Keep embed-commit versions identical between producer and verifier","Treat 'import called during commit_hash' as a classification (foreign module), not an error to retry"],"tags":["wasm","wasmer","verification","embed-commit","unimplemented","rust"],"backgroundTag":null,"analyzedSha":"031785bb6dc6b957c624e62bc64c184409c97d7b","analyzedAt":"2026-08-16T06:24:09.996Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}