Skip to content

Repository files navigation

scry — sound abstract interpretation for WebAssembly

a verification pass built inside the PulseEngine toolchain. scry over-approximates the reachable behaviour of fused Wasm Core Model modules emitted by meld, and (phase 2) lifts that analysis to Component-Model-level properties. it closes the third DO-333 technique-class gap — sound static analysis — that PulseEngine's existing deductive-proof and bounded-model-checking layers do not staff.

scry is part of the PulseEngine verification chain. it consumes meld's fused output, feeds invariants to loom's optimizer, and produces sigil-signed in-toto evidence that rivet links back to requirements.

tagline

scry sees. loom acts.

what scry is

  • sound, not unsound. scry over-approximates: it may flag behaviour that cannot happen, but it never misses behaviour that can. soundness is stated against the official Wasm operational semantics (PLDI 2017) and tracked toward mechanized proof against WasmCert-Coq.
  • the missing DO-333 leg. PulseEngine already covers deductive proof (Verus, Rocq, Lean) and bounded model checking (Kani, Z3 translation validation in loom). scry is the third class — abstract interpretation per the Cousot framework (POPL 1977) — explicitly named as the unstaffed layer in the 2026-04-22 overdo post.
  • post-meld for Core Wasm, pre-meld for Component Model. scry's Core analysis runs on the fused module meld emits, so its invariants apply directly to loom's transformation preconditions. Component- Model analysis (handles, capabilities, host effects) runs upstream of meld on the still-WIT-typed components; meld emits a minimal component-provenance custom section so scry can project the Component-Model invariants onto fused-module locations for loom, witness, and the sigil/rivet evidence chain (DD-002).
  • a reusable lattice library. the abstract domains (interval, region-memory, reachability, taint, capability, resource-lifetime) ship as a separate crate (wasm-lattice) reusable by witness for coverage-gap prediction and synth for ARM/RISC-V codegen invariant generation.
  • six safety domains, one chain. evidence scry produces earns credit in DO-178C/DO-333 (avionics), ISO 26262-6 §9 (automotive ASIL-D), IEC 61508-3 Annex B (general FS), IEC 62304 (medical Class C), EN 50128 (railway SIL 4), ECSS-Q-ST-80C (space) — by inheriting the same overdo-chain attestation story as meld and loom.

status

v3.2.4 shipped — the full v0.1 → v3.2 arc is done; scry is a working sound abstract interpreter, not a scaffold. Shipped and on crates.io: 12 pure scry-sai-* crates (10 abstract domains — interval, region-memory, call-graph

  • reachability, octagon, pentagon, known-bits/congruence, IEEE-754 float, Component-Model handle-state, linear-memory segmentation, convex polyhedra — plus the analyzer core and the viz) driving analyze() over parsed Wasm; a host wasmtime harness; runtime-trap classification (PROVEN-SAFE vs POTENTIAL-TRAP); ranked remediation guidance + a structured guidance.json; and a GitHub Pages verification dashboard.

Soundness evidence is scoped, not flattened (mirrors the dashboard's Scope & limitations block):

  • Mechanized (Rocq, admit-free): 19 .v proofs, 0 Admitted / admit / Axiom — the domain lattices + core transfers, incl. i32.add vs the OFFICIAL two's-complement wrapping semantics (WrapAdd.v).
  • γ-sweep-validated (tested, NOT mechanized): the harder transfer algorithms — float round-to-nearest, known-bits at w=32/64 (issue #105), and the polyhedra Fourier–Motzkin entailment.

Releases are cosign-signed with CycloneDX SBOMs + SHA256SUMS + SLSA v1 provenance; rivet validate is PASS. The roadmap below is historical through v3.2 (shipped); only v3.3+ items are still plans.

is this for you?

scry is for you if any of these match:

  • you ship safety-critical Wasm components through the PulseEngine pipeline and need DO-333-credit-bearing static analysis alongside Kani BMC and Verus proofs.
  • you're hitting Wasm static-analysis tools whose call graphs are empirically unsound on call_indirect (83% of real Wasm — per Lehmann et al. ISSTA 2023) and need an analysis whose soundness story is named.
  • you want sound capability-flow or resource-lifetime analysis on Component Model compositions and have noticed no such tool exists publicly yet.
  • you want invariants that the loom optimizer can consume directly to strengthen its translation-validation preconditions.

scry is probably not for you if you want:

  • a vulnerability scanner with low setup overhead — use Wasmati (Code Property Graph) for fast pattern-matching on Wasm binaries.
  • a dynamic Wasm analyzer — use Wasabi (binary instrumentation) or Wastrumentation (source-level, ECOOP 2025) for execution-trace-based analysis.
  • a Rust-only deductive verifier — use Verus or Kani directly; scry's level is Wasm, not Rust MIR.
  • the industrial commercial AI for C/Ada — use Astrée; scry doesn't target C/Ada and won't.

quickstart — three runnable examples

each example will exercise the whole PulseEngine stack: WIT-typed components → meld static fusion → scry sound abstract interpretation → loom optimization → witness coverage → sigil signed bundle → rivet traceability evidence. commands shown are aspirational and become real at the version they're tagged to.

example 1: scry-hello (v0.1)

minimum viable analysis. parses a hand-written tiny Wasm module (arithmetic only, no memory, no calls), runs the interval domain over i32/i64 locals, prints per-instruction interval invariants. no integration, no signing — proves the pipeline.

cd examples/scry-hello
bazel build //...
scry analyze target/scry-hello.wasm \
--domain interval \
--format json
# → {"invariants":[{"pc":7,"locals":[{"idx":0,"interval":"[0,255]"}]},...]}

exercises: wasm-parser, wasm-lattice (interval domain), scry CLI.

example 2: scry-fused-bounds (v0.3)

real fused Wasm module from meld, sound call-graph construction via value-domain AI on the operand stack, region-memory bounds invariants that loom can consume. produces a JSON invariant bundle.

cd examples/scry-fused-bounds
bazel build //... # WIT → wasm components
meld fuse fused-bounds.world.wit \
--output target/fused-bounds.bundle.wasm
scry analyze target/fused-bounds.bundle.wasm \
--domain interval,region-memory,reachability \
--call-graph sound \
--output target/fused-bounds.scry.json
loom optimize target/fused-bounds.bundle.wasm \
--consume-invariants target/fused-bounds.scry.json \
--enable bounds-check-elision,constant-fold
# → loom reports N elided bounds checks, M folded constants, all proven by scry

exercises: scry core (interval + region + reachability), sound indirect-call resolution per Paccamiccio et al. 2024, loom invariant ingestion.

example 3: scry-component-handles (v0.7)

Component Model resource-lifetime analysis. pre-meld pass over a composition of three components that exchange owned/borrowed handles; scry reports any use-after-drop on owned handles at link time. produces a sigil-signed in-toto attestation linkable from rivet.

cd examples/scry-component-handles
bazel build //...
scry analyze-components \
--composition components.wac \
--check resource-lifetime,capability-flow,host-effects \
--output target/component-handles.scry.json
sigil sign target/component-handles.scry.json \
--predicate in-toto-spec-v1
rivet add -t safety-solution \
--title "scry attests no use-after-drop in component-handles" \
--field evidence-type=formal-proof \
--field evidence-ref=$(sha256sum target/component-handles.scry.json | cut -d'' -f1) \
--link "supports:G-003"
rivet validate
# → safety-goal G-003 transitions from undeveloped to supported.

exercises: scry component-mode (Component Model AI), sigil attestation, rivet evidence-to-safety-goal linking, end-to-end overdo chain.

release plan

honest incremental scope, witness-style. each version closes a specific gap. signed binaries, CHANGELOG-disciplined, rivet-validated release artifacts. the per-version rivet feature artifacts (FEAT-*) are in artifacts/requirements.yaml; provisional ones for v0.2+ carry status: proposed.

versionwhat shipsverification deltaexamplefeature artifact
v0.1scry CLI; wasm-parser + interval domain on i32/i64 locals; JSON invariant output; no memory, no callsunit tests · soundness theorem stated paper-only for interval domainscry-helloFEAT-001
v0.2region-based linear-memory model (CRAB-style); per-region offset trackingproperty-based soundness tests on region+interval product(extends v0.1)FEAT-005
v0.3sound call_indirect resolution via value-domain AI on the operand stack; reachability domainproptest on indirect-call resolution vs ground-truth concrete graph; differential vs Wassailscry-fused-boundsFEAT-006
v0.4compositional summary-based interprocedural AI per Stiévenart & De Roover SCAM 2020scaling benchmark on real fused PulseEngine modules; summary-precision metrics(extends v0.3)FEAT-007
v0.5loom integration: invariant schema v1; loom consumes scry output to trigger bounds-check elision + constant foldingend-to-end test on a meld→scry→loom pipeline; loom reports invariants-derived transforms(extends v0.3)FEAT-008
v0.6sigil attestation per scry run; rivet integration; full evidence-to-requirement traceabilityDSSE-signed in-toto predicates; rivet validate links scry attestations as verified-by evidence(extends v0.3)FEAT-004
v0.7Component Model AI (per DD-002): scry analyzes original component sources; meld emits component-provenance custom section; scry projects invariants onto fused-module locations. Tracks owned/borrowed handle states, capability flow, host-call effectssound resource-lifetime detection on real WAC compositions; capability-graph soundness check; meld component-provenance round-trip testscry-component-handlesFEAT-002
v0.8taint domain (Wanilla-class noninterference) for security-property analysisproptest on relational noninterference; differential vs Wanilla on shared corpus(extends v0.3)FEAT-009
v0.9octagon + relational numerical domains for false-alarm reduction; admit-free Rocq soundness proof of the interval domain over the ℤ integer model (the proof vs the official wrapping semantics landed later at v3.0, WrapAdd.v; the WasmCert-Coq import is deferred, TE-004)Rocq build green, 0 admits; reduced false-alarm rate measured on benchmark corpus(extends v0.3)FEAT-010
v1.0six-domain credit dossier; full mechanized soundness for the v0.1+v0.2+v0.3 domain stack; SpecTec-derived transfer-function backend prototyperivet coverage at 100% across the full G-001 sub-tree; rivet validate --qualification-mode green(HW+dossier)FEAT-011

verification matrix (per shipped abstract domain)

each shipped abstract domain carries the full overdo chain. early versions allow paper-only soundness. an admit-free Rocq soundness proof of the interval domain over the ℤ integer model (Soundness.v) lands at v0.9/v1.0; at v3.0 WrapAdd.v proves i32.add sound against the official two's-complement wrapping semantics — including the wrap case (modelled directly, 0 admits, CI-gated). what remains a named, not-yet-met target (TE-004) is importing the canonical WasmCert-Coq development as the concrete model — rather than scry's own faithful re-modeling of it — and extending the official-semantics proof beyond i32.add to the other integer/float transfers (ℤ-model / γ-sweep only today).

chain layerinterval (v0.1)region-memory (v0.2)call-graph (v0.3)summaries (v0.4)taint (v0.8)
Lean / Rocq (math)TBDTBDTBDTBDTBD
Verus (SMT)interval join commutative + bottom-identity, proven up to γ (semantic equality) — repaired from an earlier false structural claim (FEAT-012)region disjointnesscall-target set monotonicitysummary join monotonicitylabel-flow monotonicity
Kani (bounded)wrap-around overflow pathsoffset overflow pathsjump-table edge casesrecursion-frontier edge casesdeclassification edges
Rocq soundness proof (ℤ integer model, 0 admits)v0.9v1.0v1.0v1.0post-v1.0
Rocq proof vs official wrapping Wasm semanticsi32.add ✓ (v3.0, WrapAdd.v, direct model)
WasmCert-Coq import as concrete model (+ other transfers)deferred (TE-004)deferreddeferreddeferreddeferred
proptestrandom concrete program ⊆ abstract resultrandom region access patternsrandom call_indirect programsrandom call graphsrandom taint flows
differential vs prior art(none specific)CRAB ground-truth on translated CWassail call-graph diffStiévenart summaries diffWanilla diff
sigil signed evidenceper analyzer runper analyzer runper analyzer runper analyzer runper analyzer run
rivetevery domain's soundness theorem linked to its safety-solutionsamesamesamesame
witness MC/DCon the scry implementation itself (Rust→Wasm)samesamesamesame

six-domain credit alignment

standardscry-specific use casecredit class scry contributes
DO-178C + DO-333avionics components that pass through the PulseEngine pipelineDO-333 §FM.4.4 "abstract interpretation" (third technique class)
ISO 26262 ASIL-DASIL-D control components running on Wasm runtimes26262-6 §9 static analysis ("abstract interpretation" recommended)
IEC 61508 SIL-4safety-related instrumentation control61508-3 Annex B static analysis credit
IEC 62304 Class Cmedical device Class C softwarestatic-analysis evidence for class C
EN 50128 SIL-4railway signaling componentsstatic-analysis credit class T1/T2
ECSS-Q-ST-80Cspace flight softwarestatic-analysis credit per ECSS-E-ST-40C
EU CRAany commercial Wasm-component product in EU"appropriate verification" evidence (Article 13)

each row is a market where the same chain (meld + scry + loom + witness

  • sigil + rivet) earns credit without rebuilding the dossier.

architecture — where scry sits

 ┌─────────────────────────────────────────────────────────┐
│ Component Model layer (WIT-typed components) │
│ ┌─ scry pre-meld (v0.7+) ─────────────────────────┐ │
│ │ resource-lifetime · capability-flow · effects │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
▼ meld static fusion
┌─────────────────────────────────────────────────────────┐
│ Core Wasm layer (fused module) │
│ ┌─ scry post-meld (v0.1 baseline) ────────────────┐ │
│ │ interval · region-memory · reachability · │ │
│ │ sound call-graph · compositional summaries · │ │
│ │ taint │ │
│ └──────────┬──────────────────────────────────────┘ │
│ ▼ invariants (JSON, signed) │
│ ┌─ loom optimizer ────────────────────────────────┐ │
│ │ bounds-check elision · constant fold · DCE │ │
│ │ + Z3 translation validation per pass │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
▼ optimized fused Wasm
┌─────────────────────────────────────────────────────────┐
│ Downstream consumers │
│ • witness ── MC/DC on the same module │
│ • synth ── AOT to ARM/RISC-V (invariants help) │
│ • kiln ── runtime executes the optimized Wasm │
│ • sigil ── signs the whole evidence bundle │
│ • rivet ── links scry attestations to requirements│
└─────────────────────────────────────────────────────────┘

shared cross-layer flows:

  • scry's Component-Model analysis runs on the original component sources upstream of meld; meld emits a minimal component-provenance custom section that maps fused-module function indices back to their originating component+function. scry uses this mapping to project Component-Model invariants onto fused-module locations (DD-002, closed 2026-05-26).
  • the wasm-lattice crate is consumed by witness for coverage-gap prediction (an over-approximation of unreachable branches narrows the witness MC/DC coverage frontier).
  • sigil signs the invariant JSON; rivet links the signed digest as verified-by evidence on the originating requirement.

design decisions worth reading first

decisionwhat's openwhere
DD-001pipeline placement: post-meld between meld and loomartifacts/design.yaml#DD-001
DD-002Component-Model AI placement: option (b) closed 2026-05-26 — scry analyzes original component sources; meld emits minimal component-provenance custom sectionartifacts/design.yaml#DD-002
DD-003soundness substrate: WasmCert-Coq + Iris-Wasmartifacts/design.yaml#DD-003
DD-004reusable wasm-lattice crate decoupled from Wasm front-endartifacts/design.yaml#DD-004
DD-005v0 domain set: interval + region-memory + reachability + sound call-graphartifacts/design.yaml#DD-005
DD-006compositional summary-based interprocedural AIartifacts/design.yaml#DD-006
DD-007sigil-signed in-toto attestations linked from rivetartifacts/design.yaml#DD-007

prior art — what we read, what we build on

every cited paper is a academic-reference rivet artifact in artifacts/research.yaml. the most load-bearing:

further reading

  • docs/intro-to-abstract-interpretation.md — friendly explainer of abstract interpretation and "soundness" for readers who've never met the term. Builds intuition with a worked safe_index example, explains the lattice/widening trick, and connects to what scry actually does on Wasm. ~10 minutes to read, no math required.
  • docs/architecture.md — how scry v0.1 fits together end-to-end: the two-component WIT split, the 8-layer Bazel build pipeline, the WAC composition contract, the runtime cross-component probe, and where each stage of the PulseEngine verification loop sits today. With mermaid diagrams.
  • docs/roadmap.md — per-version plan with research links and the composition narrative (witness-style). Verus + Rocq proof toolchain wires in at v0.2 (see FEAT-012).
  • CHANGELOG.md — Keep-a-Changelog format, read by release.yml to populate GitHub Release notes.

where to look in this tree

unknown-project/ (will be renamed to `scry/`)
├── README.md (this file)
├── rivet.yaml (project + schemas + docs)
├── schemas/
│ └── research-ext.yaml (local schema: references-paper /
│ addresses-finding / evaluates-tech
│ link types)
├── artifacts/
│ ├── research.yaml (11 papers + 7 tech evals +
│ 4 market findings)
│ ├── requirements.yaml (8 requirements + 4 features
│ [+ FEAT-005..011 proposed])
│ ├── design.yaml (7 design decisions; DD-002 open)
│ └── safety-case.yaml (4 GSN goals + 1 strategy +
│ 4 solutions + 3 contexts +
│ 3 justifications)
└── docs/
├── intro-to-abstract-interpretation.md (friendly explainer —
│ what AI is, what "sound"
│ means, where scry fits;
│ ~10 min, no math)
├── architecture.md (how scry v0.1 works:
│ components · pipeline ·
│ composition · runtime probe
│ — with mermaid diagrams)
└── roadmap.md (per-version research links +
composition narrative —
witness-style)

related projects

  • rivet — typed artifact graph + V-model traceability. scry artifacts live here.
  • meld — static WASM component fusion. scry's primary input source for post-meld analysis; scry's pre-meld pass runs upstream of meld for Component-Model properties.
  • loom — verified WASM optimizer. consumes scry invariants to strengthen transformation preconditions (bounds-check elision, constant fold, DCE).
  • witness — MC/DC branch coverage for WASM. consumes wasm-lattice's reachability for coverage-gap prediction.
  • synth — WASM-to-ARM AOT transcoder. consumes wasm-lattice for codegen invariant generation.
  • kiln — Wasm runtime for safety-critical systems. executes the scry-vetted, loom-optimized output.
  • sigil — supply-chain signing. produces the in-toto envelopes around scry's evidence.
  • spar — AADL v2.3 toolchain. scry results allocate back to AADL components for architecture-level traceability.

why this exists

PulseEngine's stack already has the deductive-proof leg (Verus, Rocq, Lean) and the bounded-model-checking leg (Kani, Z3 in loom). DO-333, ISO 26262-6 §9, IEC 61508-3 Annex B, and the rest of the credit-bearing standards recognize a third leg: abstract interpretation. the PulseEngine 2026-04-22 blog post named this gap. scry closes it.

separately: there is no publicly available sound abstract interpreter for the WebAssembly Component Model as of 2026. the spec authors themselves opened the formalization question at WAW 2025; the literature on Core-Wasm AI is young (post-2020) and growing. scry's phase-2 component pass is a real novel-contribution opportunity, not a re-implementation of existing work.

do the work once. earn credit six times. close the gap the literature named.


status of this README

this README is a requirements artifact, not a code artifact. it describes what scry will be. v0.1 is what makes the first row of the release table green. follow artifacts/requirements.yaml for FEAT-* status; provisional milestones carry status: proposed.

rivet list --type feature --format json returns the machine-readable roadmap. rivet coverage returns the evidence-to-requirement coverage. rivet impact --since HEAD~1 shows which scry artifacts a given commit changes.

if you're reading this in 2027 and v1.0 has shipped, this README should already have been replaced by a facts artifact rather than an intent artifact. if not, send a PR.

About

sound abstract interpretation for WebAssembly — the third DO-333 leg of the PulseEngine verification chain

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages