monad-developers / monad-developers/ultrafuzz

Re-evaluate sealed execution snapshots: cost/benefit after repeated campaign losses

Open
#921 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
85
Forks
18
Avg merge
11h 10m
Merged PRs (30d)
194

Description

Summary

Sealed execution snapshots have been the single largest source of lost campaign
time in long-running audits. Each individual failure has been fixed as its own
bug, but the pattern across them suggests the mechanism's cost may now exceed
what its threat model buys us. This issue is to collect that evidence in one
place and decide deliberately whether to keep, narrow, or retire it — not to
propose an immediate removal.

What the mechanism does

Before a run starts, the runtime materialises a complete, content-addressed copy
of the execution tree — application code plus node_modules — and pins a
VALIDATOR_BUILD_IDENTITY over it. Every subsequent module load is confined to
that snapshot, so the code that finishes a run is provably the code that started
it.

Observed costs

1. Snapshot size takes down hosts. A materialised generation is ~48k files /
~850 MB, re-created per generation. On a host where the temp directory was a
RAM-backed tmpfs, this exhausted memory and took the box down mid-campaign.
Nothing warned that the snapshot target was RAM.

2. Any rebuild mid-run is fatal. Rebuilding any package while a run is in
flight changes the build identity and the run dies with
sealed workflow execution file changed. Three runs in one campaign were lost
this way. The failure surfaces late and the message does not say "you rebuilt
something", so it reads as corruption.

3. Build-identity rotation makes in-flight runs unresumable. After an
identity rotation, runs sealed by a pre-rotation build cannot be resumed by a
post-rotation build at all. A multi-day run becomes permanently unfinishable if
the toolchain rotates underneath it — the work is not recoverable, only
restartable from scratch.

4. Rehash cost is superlinear in practice. See #904: the controller
lifecycle rehashes the full snapshot for every inspection command, so routine
status polling is expensive on exactly the long runs that most need monitoring.

5. Recurring confinement false-positives. #760 and #793 were both legitimate
paths rejected by confinement rather than genuine integrity violations. Each
needed a targeted carve-out. The carve-out list only grows.

The question to settle

The guarantee is real: it makes "the run was tampered with mid-flight"
detectable. The open question is whether that threat is one we actually face,
and whether it needs to be enforced by whole-tree confinement rather than
something cheaper.

Cheaper points on the spectrum, roughly in increasing order of strength:

  • Hash the tree once and record the digest in run metadata — detect drift at
    resume, do not confine every module load.
  • Confine only first-party package code, and trust node_modules at a pinned
    lockfile digest.
  • Keep full confinement, but make identity rotation forward-compatible so
    in-flight runs survive it (this alone would remove cost #3).

Risks of narrowing or removing

  • Loses in-flight tamper detection. Worth stating plainly: no one has reported
    an actual tamper event that this caught. The failures above are all
    self-inflicted.
  • Reproducibility claims that cite the sealed snapshot in report provenance
    would need rewording.
  • The confinement carve-outs (#760, #793) encode real invariants; removing the
    mechanism without reading them risks re-introducing the underlying bugs.

Asks

  1. Confirm whether in-flight tamper detection is in our threat model, or
    inherited from one we no longer hold.
  2. If it is not, cost out the "hash once, verify at resume" option.
  3. Independent of that decision, fix cost #3 — an identity rotation should never
    strand a run that is already in progress.

Labelled help wanted: this needs someone with the original design context, not
just someone willing to delete code.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No implementation files are named. Start by reviewing issues #904, #760, and #793, then trace the sealed snapshot and build-identity lifecycle to understand the reported costs and carve-outs. Done means documenting the threat-model decision, costing the hash-once alternative if appropriate, and ensuring identity rotation does not strand in-flight runs.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, security
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.