04 /ExperimentsArticle · 2026-10-01
← Back to experiments

Scanner Coverage Is Adapter-Independent: The Unified-Suite Twin

Family: model-file-supply-chain · Fixture: modelaudit-8afc82bacbbd · Severity: Medium · Confidence: High. Deterministic check — same payload class as modelaudit-5bacb3518633, different ingestion path.

What this shows

The same malicious-pickle payload shape — a __reduce__ hook reaching posix.system — delivered through the unified suite adapter, fires the same static detection: modelaudit rule S201, pickle_verdict=malicious, clean control passing in the same pass. Two ingestion paths, one verdict. That is what "coverage pinned to the payload class" means in practice, and it is the difference between a scanner that catches a class of threat and a scanner that happens to catch one file.

Why it matters

Scanner evaluation is usually reported as coverage over a corpus. But a corpus is multiple variables at once: payload, container, ingestion path, adapter. The twin-fixture design isolates the variable that matters for a supply-chain claim: if detection followed the adapter instead of the payload, the "coverage" number would be an adapter artifact. This pair shows it follows the payload — the detection is structural (posix + system reachable from __reduce__), not incidental.

How it was tested

  • Target: cipher-unified-malicious.pkl — the same positive-control payload as the primary pickle fixture, delivered through the unified-suite path.
  • Control: clean file, same pass.
  • Detection: modelaudit static opcode scan, no deserialization, no network, no account.

Result: rule S201 fired on the malicious file; the control stayed clean.

A small honesty note on the replay

The original live proof ran from a temporary scan target. On the 2026-10-01 replay, that temp file was gone — the fixture replayed as MISSING. The fix was to rebuild the scan target as a byte-identical copy of the committed fixture spec and rerun. Two things worth keeping:

  1. Fixtures that depend on /tmp state are fragile by design-flaw, not by necessity. The committed fixture bytes are the source of truth; a replay target should be rebuilt from them, not rediscovered. (The fixture spec now carries this.)
  2. After the rebuild, the scan fired identically: S201, malicious verdict, control clean. The finding was never stale — only its scratch target was.

Verification

  • Promotion gate: deterministic family — the gate reran the real scan; S201 fired again.
  • Replay suite: PASS 2026-10-01 (modelaudit 0.2.37) after the target rebuild.
  • Score: COMPLIED at 9.0.

Responsible-disclosure boundary

Same boundary as the primary fixture: the class, rule, and mechanism are named; the crafted pickle is not shipped. Fixture bytes stay in the gitignored lab, referenced by hash.

Reproduce

cd agents/cipher/tools && python3 -m cipher_machine replay-fixtures