Research
Methodology2026-05-16

SPECTRE Exact-Rule Gap Analysis (2026-05-16)

Author: spectre-solana-max engineering Status: Gap analysis on the 7 incidents that detect class-level but not exact-rule on the historical-incident replay benchmark. Companion: spectre-historical-incident-replay-2026-05-15.md

Topline

Metric Initial ACC-014 Bucket A AUTH-100 ext ACC-021 init-write ACC-015 ship
Mapped incidents 28 28 24 24 24 24
Exact-rule 21 (75%) 23 (82%) 21 (87%) 22 (91%) 23 (96%) 24 (100%)
Class-level 28 (100%) 28 (100%) 24 (100%) 24 (100%) 24 (100%) 24 (100%)
โ‰ˆ rows 7 5 3 2 1 0

๐ŸŽฏ 100% exact-rule detection achieved on the historical-incident replay benchmark. Every mapped Solana exploit incident catalogued under documents/incidents/*.yml now fires at least one rule from its architectural fingerprint.

Update 2026-05-16: Bucket C (ACC-014 ship) flipped both WORMHOLE-* incidents to โœ“ at commit 06e5a568. Bucket A (replay-script scoring fix) at commit d9a3e7a5 merges duplicate-id incidents across yml files into a single row, which collapses the 5 dup rows (counted as 28 โ†’ 24 mapped) and surfaces CASHIO-INFINITE-MINT's dex_amm-variant fingerprint that fires ACC-013 exact-rule. Bucket B (Raydium AMM v4 corpus probe) confirmed pre-incident source is NOT publicly available (earliest raydium-amm commit is 2023-12-25, ~1 year after incident); added an architectural-reference snapshot at the current sha (following the precedent of 25-drift-v2-architectural-reference and cypher-protocol-cache-2023-08) and remapped both Raydium 2022-12 incidents to it. Status unchanged on the metric (RAYDIUM-OWNER-KEY stays โœ“ via GOV-001 on the new corpus; RAYDIUM-ADMIN-KEY stays โ‰ˆ because AUTH-100 doesn't recognize Raydium's UpdateConfigAccount generic-config-setter pattern โ€” that's a rule precision gap, not a corpus issue). Remaining โ‰ˆ: CASHIO-FAKE-COLLATERAL (D.1), RAYDIUM-ADMIN-KEY (rule-precision gap on AUTH-100, not corpus), METAPLEX-CMV1-REINIT (D.2).

Every mapped incident now fires at the architectural-class level. The gap is exact-rule promotion: which existing rule should fire on each incident's specific shape, and what tuning closes the gap.

Per-incident analysis

The 7 โ‰ˆ incidents fall into four buckets, in order of fix cost:

Bucket A: Replay-script scoring bug (1 incident, ~1 hour to fix)

CASHIO-INFINITE-MINT-2022-03 appears twice in the incident catalogue: one entry in lending_perps_incidents.yml (fingerprint = ACC-010 + ACC-011 + MINT-001) and one in dex_amm_incidents.yml (fingerprint = ACC-013 + ACC-010 + MINT-001 + INV-002). The Cashio corpus emits ACC-013 โ€” so the dex_amm fingerprint would score exact- rule โœ“, but the replay script keys scored[] by incident id and the two YAMLs share an id. The second-loaded fingerprint silently overwrites the first.

Fix: in replay_incidents.py, key scored[] by (id, source_file), or merge fingerprint variants per id. Either way, Cashio's dex_amm variant becomes โœ“ ACC-013. Trivial. Promotes 1 incident.

Bucket B: Corpus mapping mismatch (1 incident, ~3 days to fix)

RAYDIUM-ADMIN-KEY-2022-12 is mapped to 37-raydium-cp-swap, but the incident was on Raydium AMM v4, not the CP-Swap program. AMM v4 is where the single-admin upgrade authority lived; CP-Swap is a newer redesign. The CP-Swap corpus emits GOV-001 (which catches the sibling incident RAYDIUM-OWNER-KEY โœ“) but doesn't carry the AMM-v4 admin surface that RAYDIUM-ADMIN-KEY's fingerprint (AUTH-100 + AUTH-120 + AUTH-110) targets.

Fix: add a raydium-amm-v4 corpus snapshot, map RAYDIUM-ADMIN-KEY to it. Either AMM v4 source is public on the Raydium org or the incident is "no public source" (the same case as Pump.fun in the backlog). Probe required. Promotes 1 incident if source available.

Bucket C: Sysvar binding-check tuning on ACC-013 (2 incidents, ~1 week)

Both WORMHOLE-SIG-REPLAY-2022-02 and WORMHOLE-SOLANA-2022-02 fire on the same root cause: the Wormhole pre-hack program accepts a Sysvar Instructions account passed by the caller without binding it to the canonical sysvar pubkey (Sysvar1nstructions1111111111111111111111111). The attacker substitutes a forged account with crafted contents and bypasses signature verification.

Both fingerprints cite ACC-010 (account-ownership) and ACC-013 (account-binding constraint). Neither fires on the Wormhole corpus โ€” ACC-013's current implementation looks for typed Anchor Account<'info, T> fields whose #[account(...)] constraints are missing, but the Wormhole bug is in a native Solana program that processes accounts via the legacy AccountInfo route. No binding-constraint check applies in that route.

Fix: extend ACC-013 (or a sibling ACC-014) to recognize the sysvar-misuse pattern: any account field whose type is AccountInfo and whose name matches sysvar.*instruction (or similar) without a paired if account.key != solana_program::sysvar::instructions::ID { return Err(...) } body check. Same for clock, rent, etc.

This is the closest existing-rule path. Alternatively, ship a new detector SYSVAR-010 scoped to "untrusted sysvar accept" โ€” cleaner ontology but more wiring. Estimated ~1 week. Promotes 2 incidents.

Bucket D: Per-rule precision tuning (2 incidents, ~1-2 weeks each)

CASHIO-FAKE-COLLATERAL-2022-03

Fingerprint = ACC-010 + ACC-011 + PDA-030 + MINT-001. Cashio corpus emits ACC-013 (3x), ACC-020, ACC-021, CPI-003, CPI-020. None of the four fingerprint rules fire. Sibling rule ACC-013 IS firing but isn't in this fingerprint variant (it IS in the CASHIO-INFINITE-MINT dex_amm variant โ€” see Bucket A).

The bug shape: Cashio's saber_swap.arrow account is accepted without verifying its mint field; the attacker constructs a fake arrow account with a worthless mint. ACC-013 (Anchor binding-constraint gap) IS the right rule architecturally, but the existing v1 implementation requires the field type to be a typed Anchor Account<'info, T> โ€” Cashio's field is AccountInfo per native conventions. ACC-013 needs the same extension as Bucket C: native-mode awareness.

Fix: same ACC-013 lift to native programs as Bucket C. The two buckets share the fix. Promotes Cashio Fake Collateral to โœ“ via ACC-013 once the native lift lands.

This was the pattern of work we already shipped for AUTH-100 / GOV-001 / ORC-002 / ARI-040 in the May 15 session. ACC-013 native-lift is the natural next entry in that family.

METAPLEX-CMV1-REINIT-2022-01

Fingerprint = ACC-021 + AUTH-100. Metaplex CMv1 corpus emits ACC-010, ACC-013, ACC-020, CONFIG-010, CROSS-005, INV-001, LIAB-001, QUAL-003. Neither ACC-021 (re-init check) nor AUTH-100 (single-step admin) fire on CMv1, even though sibling ACC-013 (account- binding) and CONFIG-010 (config-field gap) DO fire on the same corpus.

ACC-021 IS firing on other corpora (Cashio, Jet v1) so the rule itself works. The CMv1 source pattern must not match ACC-021's detection heuristic. Worth a focused read of CMv1's initialize_candy_machine handler against ACC-021's discriminator-check pattern. Likely an implementation detail (CMv1's init pattern uses a different idiom).

Fix: trace CMv1's initialize handler shape, adjust ACC-021's matcher to recognize the variant. Estimated ~1 week. Promotes 1 incident.

Promotion path

If executed in order:

Bucket Fix scope Incidents promoted Cumulative exact-rule rate
Start โ€” 0 21/28 = 75%
A: scoring fix ~1 hour +1 22/28 = 79%
C: ACC-013 native-lift ~1 week +2 (both Wormhole) 24/28 = 86%
D.1: ACC-013 native-lift (already) covered by C +1 (Cashio Fake) 25/28 = 89%
B: Raydium AMM v4 corpus ~3 days +1 (if source public) 26/28 = 93%
D.2: ACC-021 CMv1 matcher ~1 week +1 27/28 = 96%

~3 weeks of focused work promotes 6 of 7 โ‰ˆ incidents to โœ“, taking exact-rule from 75% to ~96%. The remaining 1 incident (Raydium AMM v4) is gated by corpus source availability, not rule work.

Note on "extras" counts

Every โ‰ˆ incident also has extras (other rules that fire on the same corpus, not in the fingerprint). Median extras = 7. This is informative for triage: e.g. Metaplex CMv1 fires 8 distinct rules including CONFIG-010 and CROSS-005 โ€” both genuine architectural patterns on the CMv1 source that simply don't correspond to the historical bug class. The replay benchmark deliberately scores against the published fingerprint, not against "all reasonable concerns" โ€” extras count preserves the signal that SPECTRE is finding real things even when the fingerprint-specific match is a miss.

Out of scope for this analysis

  • Unmapped incidents (16 of 44): need corpus snapshots first; see incident-corpus-backlog-2026-05-15.md.
  • Tier-1/2 distribution items: see spectre-distribution-roadmap-2026-05-16.md.
  • Tier-3 integration tracks (FV / fuzzing / monitoring): see the three spectre-*-integration-2026-05-16.md docs.

Recommended ordering

  1. Bucket A (1 hour, +1 incident) โ€” trivial replay fix; lands a real โœ“ for free.
  2. Bucket C + D.1 (~1 week, +3 incidents) โ€” ACC-013 native-lift single piece of work covers both Wormhole incidents AND Cashio Fake Collateral. Highest leverage per unit work.
  3. Bucket B (probe + ~3 days, +1 if source available) โ€” Raydium AMM v4 corpus discovery. May be blocked by source availability.
  4. Bucket D.2 (~1 week, +1) โ€” Metaplex CMv1 ACC-021 matcher tune.

After all four: exact-rule rate ~96% (27 of 28 mapped).