anticsdecoded|Portfolio
SEC|2026
/audits / PIRATE.cpp
cat /audits/PIRATE.cpp
NODE: PRIVATE

Privacy L1 (Komodo / Zcash fork)

// engagement
protocolPirate
categoryPrivacy L1 (Komodo / Zcash fork)
kindprivate · Private
date2026-07
duration2 weeks
languageC++
chainsPirate/Komodo
nSLOC7,180
// findingsNODE: 2 FND
critical0
high1
medium1
low0
info0
gas0
// summary

Private audit of Pirate (pirated), a fully-shielded Komodo/Zcash-derived L1 daemon (Sapling, Equihash PoW), covering two unauthenticated P2P denial-of-service paths reachable after a normal handshake: a coin-import mempool crash (Medium) and invalid-PoW header acceptance (High, marked out of scope).

// methodology
  • Manual review
  • PoC development
  • P2P fuzzing
// scope
pathnsloc
src/main.cpp5,200
src/script/script.cpp1,300
src/importcoin.cpp380
src/primitives/transaction.h300
total7,180
// findings
H-01highacknowledged

Unauthenticated P2P headers with invalid PoW accepted as best header state (out of scope — Sybil)

`AcceptBlockHeader()` calls `CheckBlockHeader(..., fCheckPOW=0)`, so unauthenticated P2P headers with no valid Equihash solution are indexed as `BLOCK_VALID_TREE` and can be promoted to `pindexBestHeader`, poisoning header/sync state with work that can never validate as full blocks. Marked out of scope by the PirateNetwork team (a material effect would require Sybil-scale influence); retained for the technical record.

M-01mediumacknowledged

Empty coin-import push in an unauthenticated P2P tx crashes a synced node

An unauthenticated peer relays a coin-import-shaped tx (`vin[0].prevout.n == 1000000000`) whose `scriptSig` is an empty push, so the mempool standardness path calls `CScript::IsCoinImport()` — which dereferences `data.begin()[0]` without a non-empty check — before the safe `VerifyCoinImport()`, crashing a synced production node with SIGSEGV. Assigned Medium by the PirateNetwork team.