verify-bundle — Heimdall's wasm guest for Holger's update bundles
Heimdall is a defensive sandbox. This guest reads a holger.update-bundle/v1
(.holger.znippy) that came from somewhere nobody trusts, so that the Holger server
never parses those bytes itself. Its tests exercise its own containment only.
Bytes in, a verdict and named outputs out; no host access. In order:
- the znippy v0.7 container (footer, Arrow IPC index framing walked before arrow reads it, chunk geometry, per-chunk BLAKE3, member names through the path guard, member count, the bomb shape from the declared sizes) — before a blob byte is read;
- the control members only, under their own caps;
- the release signature (Ed25519 over X.509, pinned or rooted, as Holger signs), the approvals and the two-person rule;
- every other member, named by the signed manifest before it is read;
- Holger's full verification order (content list both ways, envelope, expiry, evidence, target, anti-rollback);
- every DSSE envelope: payload type, then every signature by a pinned signer, and only then the in-toto statement, which must name a payload of this bundle.
Verdict: Accepted (outputs: verify-report.json plus the payload and evidence
members) or Refused { code, reason }. emit-file takes one plain file name, so a
member path is emitted under an injective name (payload/fw.bin is
payload+2ffw.bin; see output_name), and the report lists both. In the wasm export
(src/wasm.rs, bound to crates/heimdall-wasm/wit/heimdall.wit) the WIT refusal is
one string, so the reason starts with the code in brackets. The one job input is the
.holger.znippy itself; everything else arrives as job parameters. Codes are Holger's frozen holger-update-<n>
wherever Holger's own verifier refuses the same thing, else heimdall-bundle-<n>
(1 parameters, 2 archive, 3 codec, 4 DSSE, 5 DSSE binding, 6 parser panic).
Parameters: a RON VerifyParams document or Heimdall's string pairs (now,
policy, product, model, revision, accepted, dsse, emit); see
src/params.rs.
OpenZL: znippy compresses members with OpenZL, a C library. With the default
feature openzl the guest compiles OpenZL's decoder (vendored in openzl/, built
for wasm32 by build.rs against wasi-libc headers; needs clang and the
wasi-libc package, see ci/ci.Containerfile) into the module, which still
imports nothing but the WIT. A frame is decoded only after its header declares
exactly the size the index declares. --no-default-features refuses compressed
members by name (heimdall-bundle-3). Details and the open risk:
docs/OPENZL-WASM.md.
cargo test --release # unit, integration, differential, proptest, and
# tests/wasm_e2e.rs: the component in the real host
cargo build --release --target wasm32-unknown-unknown
cargo +nightly fuzz run archive fuzz/seeds/archive # also: bundle dsse_envelope params certificate openzl_frame