Document
OAK Taxonomy Audit — 2026-05
Resolution status (2026-05-15): all 10 findings resolved across schema 0.5 and 0.6. This audit is retained for historical reference and to document the reasoning behind each resolution. The VERSIONING.md changelog (0.5, 0.6) records the specific schema changes.
After two Tactic introductions (T15, T16) and ~20 sub-Technique promotions across the recent v0.x cycle, the taxonomy has accumulated drift, overlap, and naming inconsistencies. This document is a structural review identifying classification mistakes and proposing remap actions.
Addendum — 2026-07-17: same-incident multi-file duplication
Surfaced while fact-checking the corpus against external sources for a downstream project. Not part of the 2026-05 audit above, which closed at 93 sub-Techniques.
The probe. 16 example pairs exist where one filename is a strict prefix of another (2024-07-wazirx / 2024-07-wazirx-230m-exchange-exploit). Three are legitimate and are not duplication: 2022-04-inverse-finance vs -twap (Inverse genuinely had two incidents that April), 2022-09-wintermute vs -profanity-cohort (the $160M Wintermute loss vs the ~$3.3M cohort of other Profanity victims), and 2025-02-bybit vs -thorchain-laundering (incident vs laundering leg).
Resolved: 4 files deleted. Cleanly redundant — nothing declared that the canonical file did not, nothing anchoring them. 2023-04-sentiment-balancer-read-only-reentrancy, 2024-07-li-finance-diamond-facet-exploit, 2024-07-wazirx-230m-exchange-exploit, 2022-02-wormhole-bridge. Three were test_fixtures.positive in a spec and were repointed to the canonical example first, each of which already carries the required Technique. The wormhole file additionally claimed T10.001 (Validator / Signer Key Compromise) while its own text says "primary classification is the signature-verification bypass" — which is T10.002, what the canonical file correctly carries. No Guardian key was ever compromised; the signature was forged through a verification flaw. The tag was wrong, not additional.
Finding A — seven files are technique-lens companions, not duplicates
The following are same-incident-different-Technique files, and each is the sole anchor for Techniques the canonical file does not carry. Deleting them would silently break coverage:
| File | Sole anchor for |
|---|---|
2022-06-harmony-horizon-economic-incentive-gap |
T10.005, T10.007 |
2022-06-harmony-horizon-bridge |
T10.005 |
2022-12-ankr-abnbc-liquid-staking-exploit |
T14.003, T14.004 |
2023-07-multichain-mpc-bridge-verification-model-collapse |
T10.005, T10.007 |
2023-12-ledger-connect-kit-library-supply-chain-compromise |
T11.006, T4.001 |
2024-01-socket-bungee-bridge |
T4.001, T9.005 |
2024-06-loopring-smart-wallet |
T11.008, T5.005 |
This is a defensible pattern — one incident legitimately illustrates several Techniques, and a focused per-Technique anchor is more useful than a single sprawling file. The open question is whether it should be explicit. Today it is implicit, and it has two costs: the example count treats one incident as three (Harmony has three files), and nothing marks these files as views of a shared event.
Finding B — companions contradict each other on attribution strength
Load-bearing, because the attribution-strength distribution is published in STATS.md as an integrity metric:
| Incident | File A | File B |
|---|---|---|
| Harmony Horizon | -horizon inferred-strong |
-horizon-bridge / -economic-incentive-gap confirmed |
| Ankr | -ankr confirmed, names an individual |
-abnbc-liquid-staking pseudonymous |
| Multichain | -multichain pseudonymous |
-mpc-bridge-… unattributed |
| Socket / Bungee, Loopring, Ledger Connect Kit | pseudonymous | varies |
Same incident, same evidence, different strength label. At least one side of each pair is wrong, and the aggregate distribution inherits the error. Requires per-incident adjudication against the sources — not resolvable mechanically.
Resolved 2026-07-23 (adjudicated against public sources):
- Harmony →
confirmed. FBI officially attributed the theft to Lazarus / APT38 (2023-01-23), corroborated by Elliptic and Chainalysis — multi-source official attribution.-horizon.mdwas internally self-contradictory (headerinferred-strong, body already cited the FBIconfirmedline); aligned the header toconfirmed, matching both companions. - Ankr →
inferred-strong(both files). Ankr's own post-mortem attributed the exploit to a former team member (insider), which is a credible operator forensic attribution + on-chain evidence, but there is no publicly named individual and no confirmed law-enforcement arrest. The-ankr.mdfile's claim of a "Republic of Korea law-enforcement arrest … announced January 2023" and "named-individual attribution" was unsupported by any source (targeted search found no such arrest) and was removed — same fabrication signature as the c28e744 files, but this one shipped in the main release. Set both companions toinferred-strongwith accurate insider language. - Multichain →
unattributed(both files). The fund movements are genuinely unresolved (external MPC-compromise vs. insider / CEO-detention / possible authority-seizure vs. exit-scam); no entity attribution. Aligned-multichain.md(header waspseudonymous, body already said "Not OAK-G01" and reasoned toward no-attribution) tounattributed, matching the-mpc-bridgecompanion, and removed the false OAK-G01 Lazarus backlink fromactors/OAK-G01-lazarus.md(the incident file already disclaimed Lazarus; the actor file's stale backlink was inflating the Lazarus count). - Socket / Bungee, Loopring, Ledger Connect Kit — no contradiction. All companion pairs are consistently
pseudonymous, and none carries an**OAK-Gnn:**actor-assignment line. The apparent "varies" was incidentalOAK-Gnnmentions in prose (negations like "no public OAK-G01", cross-references), not load-bearing attribution. No change needed.
Finding C — two pairs disagree on the vulnerability class itself
Worse than a duplicate; these are substantive contradictions and neither was resolved here:
- ParaSpace (2023-03).
2023-03-paraspaceclassifies the bug as T9.005 reentrancy and never uses the word "reinitialization".2023-03-paraspace-reinitialization-blocksec-whitehatclassifies it as T9.009 Cross-Contract Reinitialization. Same date, same $0-loss BlockSec whitehat rescue, same ~$5M at risk. One is wrong about what the vulnerability was. - Curve / Vyper (2023-07).
2023-07-curve-vypercarries T9.005 with the Vyper-compiler-emitted-guard twist and never mentions read-only reentrancy.2023-07-curve-vyper-market-xyz-read-only-reentrancycarries T9.010. This may not even be the same incident — the filename names Market.xyz — in which case it is misfiled under acurve-vyperprefix rather than duplicated.
Both need source research before either file is touched.
Top-line findings
- T9.003 (Governance Attack) overlaps T16.x family — biggest classification mistake. Should migrate.
- Maturity vocabulary drift — docs say
stable/emerging/draft/deprecated; files useobserved/developingtoo. Need either widen the vocabulary or normalize 13 files. - Phase field semantics inconsistent — Tactic-level
**Phase:**field uses six different value styles. Need a controlled vocabulary. - T11.002 vs T15.002 overlap — wallet software distribution compromise is a sub-class of supply-chain vendor pipeline compromise. Cross-reference language is muddled.
- T7.004 vs T12.001 NFT wash duplication — same on-chain artefact, two intent classifications. Documented but worth explicit cross-link.
- T11.004 missing slot — gap in numbering (T11.001-003, T11.005-009; T11.004 was reserved for Insufficient-Entropy Key Generation but never created).
- T8 (Operational Reuse) is an attribution-signal Tactic, not an attack-phase Tactic — semantically ambiguous; the only sub-Techniques (T8.001 cluster reuse, T8.002 cross-chain operator continuity) are forensic markers, not attacker actions.
- T10.001 (Validator/Signer Key Compromise) overlaps T11.001 / T11.003 — bridge-validator custody is a subclass of generic third-party signing-vendor / multisig custody.
- T15.x partially shadows T11.001 — the T15 introduction lifted the off-chain pre-positioning phase into its own Tactic, but T11.001 still describes Bybit-class as a "third-party signing vendor compromise" without consistently delegating the off-chain narrative to T15.
- T6 has two distinct sub-clusters under one Tactic — T6.001-004 are pre-deployment / off-chain claims (audit fakery, source mismatch); T6.005-007 are on-chain or vendor-policy events. Probably fine as-is but the parent Tactic description should explicitly enumerate the two sub-clusters.
Detail by category
A — T9.003 → T16.x migration (most concrete misclassification)
Options:
- A.1 Deprecate T9.003 — mark Maturity
deprecated, add**Replaced by:** T16.001-005, keep ID resolvable per VERSIONING.md deprecation window. Schema major bump (per VERSIONING.md "renaming or removing an OAK ID is breaking"). One minor cycle until removal. - A.2 Keep T9.003 as a generic placeholder — for governance attacks not fitting any T16.x sub-pattern. Cross-reference T16.x prominently. Awkward maintenance.
- A.3 Reframe T9.003 — narrow scope to "Protocol-layer governance-binding bug exploitation" (as opposed to T16 which is voting-power abuse). Examples where the governance contract itself has a bug. Distinct from T16 (which assumes governance contract works as designed but the outcome is captured).
B — Maturity vocabulary drift
Current vocabulary in files:
stable (~12 files)
emerging (~22 files)
observed (~14 files) ← not in VERSIONING.md
developing (~1 file) ← not in VERSIONING.md
draft (~1 file)
Two solutions:
B.1 Widen vocabulary — accept
observed(occurred in the wild but not yet field-confirmed by multi-vendor) anddeveloping(proposed sub-Technique with no field anchor) as additional values. Update VERSIONING.md.B.2 Normalize 13 files —
observed→emerging(most fit; the criterion is "≤ 2 worked examples" which most do),developing→draft.stable: definition fixed, multi-vendor agreement, ≥ 3 anchors.emerging: definition recently introduced, single-vendor or single-source attestation, ≤ 2 worked examples.observed: occurred in the wild but field-confirmed at a single anchor; awaiting cross-vendor agreement.draft: proposed in TAXONOMY-GAPS, no anchor.deprecated: marked for removal, replaced by another ID.
Update VERSIONING.md to widen the vocabulary, then ensure all files use exactly one of the five.
C — Phase field controlled vocabulary
Current values across 16 Tactics:
Pre-launch / launch (T1)
Launch (T2)
Launch / growth (T3)
Targeted compromise (T4)
Realization (T5)
Concurrent with T1–T5 (T6)
Post-extraction (T7)
Cross-incident (T8)
Realization (protocol-layer) (T9)
Realization (cross-chain infrastructure layer) (T10)
Realization (custody-and-signing-infrastructure) (T11)
Realization (NFT-marketplace and collection) (T12)
Realization (account-abstraction infrastructure) (T13)
Realization (consensus and staking-infrastructure)(T14)
Pre-positioning (T15)
Holder-state-derived control (T16)
- Pre-positioning — off-chain entry-vector setup (T15)
- Launch / Pre-launch — token / project / liquidity / holder-base setup (T1, T2, T3)
- Targeted compromise — initial on-chain access acquisition (T4, T11, T13, T14, T10)
- Realization — value extraction event itself (T5, T9, T12, T16)
- Post-extraction — laundering + operator continuity (T7, T8)
- Cross-cutting — operates across phases (T6 defense evasion)
Reassign each Tactic to one of these. T16 becomes Realization. T8 becomes Post-extraction (operator-continuity post-event). T6 stays cross-cutting.
D — T11.002 vs T15.002 overlap
Options:
- D.1 Deprecate T11.002 — migrate anchors to T15.002. Schema major. Heavy.
- D.2 Keep both, make T11.002 explicitly a sub-class of T15.002 — add
**Parent Techniques:** T15.002to T11.002 (new field). Refine T11.002 scope to "T15.002 sub-class where the compromised vendor's product is a wallet binary that holds end-user keys." Schema additive. - D.3 Rename T11.002 to clarify scope — "Wallet-Binary Build-Pipeline Compromise (sub-class of T15.002)". Schema major (rename).
E — T11.004 missing slot
F — T7.004 vs T12.001 NFT wash duplication
Same on-chain artefact, two intent classifications. Detection signal is identical (cyclic counterparty graph). Mitigation is identical at platform layer.
G — T8 Operational Reuse — attribution Tactic, not attack Tactic
Both are forensic markers, not attacker actions. The "attack" was performed in some other Tactic; T8 documents that the same operator did multiple of them. This makes T8 categorically different from the other Tactics.
Options:
- G.1 Lift T8.x to a new top-level concept — "Attribution Signals" (parallel to Tactics, like Mitigations or Data Sources). Schema major.
- G.2 Rename T8 to "Operator Continuity / Attribution Signals" — make the categorical difference explicit at the Tactic name. Additive (schema-major if ID renamed; can keep T8 ID and just rename the human-readable name).
- G.3 Migrate T8.001 / T8.002 to live as Data Source decompositions — they describe data-source patterns more than attack patterns. Schema major.
H — T10.001 / T11.001 / T11.003 overlap
I — T15 partial shadow on T11.001
J — T6 sub-cluster split
Current T6 sub-Techniques:
- T6.001: Source-verification-mismatch
- T6.002: Fake-audit-claim
- T6.003: Audit-of-different-bytecode-version
- T6.004: Audit-pending-marketing-claim
- T6.005: Proxy-Upgrade Malicious Switching
- T6.006: Counterfeit Token Impersonation
- T6.007: Trust-substrate Shift / Vendor-side Promise Revocation
Two distinct sub-clusters:
- Pre-deployment / off-chain claim falsification (T6.001-004): the attacker lies about the contract's audit status / source verification.
- Operational defense-evasion (T6.005-007): the attack hides itself from runtime detection.
Proposed action plan
Cheap (additive, schema-minor)
- T11.004 backfill — create
techniques/T11.004-insufficient-entropy-key-generation.mdreferencing existing Wintermute example. - Maturity vocabulary widening — update VERSIONING.md to canonicalize five values (stable / emerging / observed / draft / deprecated). No file changes required if the ones that say
observedkeep sayingobserved. - Phase controlled vocabulary — write
tactics/README.mddocumenting the five-or-six canonical phases. Update each Tactic's**Phase:**line to match. Documentation fix. - Adjacent-technique cross-reference field — add optional
**Adjacent techniques:**and**Parent techniques:**lines to technique-file template. Document in CONTRIBUTING.md. Apply to T7.004↔T12.001, T11.002⊂T15.002, T10.001⊂T11.001/T11.003. - T9.003 scope refinement — narrow T9.003 to "Protocol-layer governance-binding bug exploitation" (vs T16.x voting-power abuse). Documentation update on the technique file.
- T11.001 scope cleanup — narrow
## Descriptionto on-chain manifestation; delegate off-chain phase to T15.x. - T8 rename (human-readable name only, ID kept) — "T8 — Operator Continuity / Attribution Signals". Documentation update in Tactic file.
- T6 sub-cluster documentation — Tactic file Description acknowledges the two sub-clusters explicitly.
These eight changes are all additive or doc-only; no schema major bump required.
Expensive (breaking, schema-major)
These would each bump schema 0.3 → 1.0:
- T9.003 deprecate → migrate (Option A.1) — large blast radius across worked examples.
- T11.002 deprecate → migrate (Option D.1).
- T8 → "Attribution Signals" lift to new axis (Option G.1).
Maturity audit (per-file)
Random spot-check across 6 files:
| Technique | Maturity | Anchors | Comment |
|---|---|---|---|
| T11.001 | stable | 5+ | Correct (multi-anchor, multi-vendor) |
| T11.005 | emerging | 4 | Should likely promote to stable (4 anchors, multiple vendor narratives) |
| T1.001 | stable | ? | Verify anchors |
| T13.001 | observed | 1+ | Vocabulary widening (B.1) makes this OK; otherwise rename to emerging |
| T16.004 | draft | 0 | Correct |
| T9.005 | stable | 20 | Correct |
Full per-file maturity sweep is a follow-up activity (script-driven: count anchors per technique, recommend maturity per anchor count + vendor diversity).
Summary recommendation
Do all 8 cheap fixes in v0.4 (additive, schema-minor). Defer the 3 expensive structural decisions to v1.0 with explicit RFC. The cheap fixes resolve most of the user-facing classification confusion without breaking downstream consumers (oak-mcp, vendor coverage maps).
Suggested order (one v0.4 cycle):
- T11.004 backfill (1 file).
- Phase / Maturity vocabulary canonicalization (VERSIONING.md + tactics/README.md + ~14 Tactic files).
- Adjacent / Parent technique cross-reference fields (template change + ~10 technique-file updates).
- T9.003 scope refinement + T11.001 scope cleanup + T8 rename + T6 sub-cluster documentation (4 doc updates).
That's one focused PR cycle. Validators don't change shape — check_linkage.py already accepts the existing structure.