Loading
Add native security fuzz targets and decoder guards
Security-sensitive parsing and message handling need reusable fuzz corpora. This change adds five native Go fuzz targets, runs them in CI, and closes two decoder edge cases.
- Fuzz targets:
FuzzParseMemo,FuzzNewAddress,FuzzRPCVersion(Solana RPC version decoding),FuzzFrostEvidenceDecodeandFuzzFrostSignedPayload(tampering with FROST signed statements). Inputs are size-capped. The seed cases also run under ordinarygo test.FuzzRPCVersionadds theemptyandnullreproducers undertestdata/fuzz. - Decoder fixes:
UnmarshalFrostEquivocationEvidencenow rejects any input that doesn't re-marshal to the same bytes.RPCVersion.UnmarshalJSONnow rejects empty andnullinput, which it previously accepted as version zero. - Memo panic classification: recovered panics in
ParseMemo/ParseMemoWithTHORNamesnow wrap anerrMemoPanicsentinel. The fuzz target useserrors.Isto tell a real panic from a validation error that echoes the memo text back. The error text is unchanged.reference:memos are exempt: they check their embedded memo through a keeper, and keeperlessParseMemohas none, so the panic there is known and recovered. A new test checks that a validation error quoting the panic text isn't classified as a panic. - Runner:
scripts/test-security-fuzz.shruns the targets, each in its owngo testcall.FUZZ_TARGETpicks one target andFUZZ_TIMEsets the budget. It persists only this module's fuzz corpus viaFUZZ_CORPUS_DIRand leaves the Go build cache alone. Before fuzzing, it clears this module's subtree of$GOCACHE/fuzz, copies the corpus in, and copies it back out on exit. It holds aflockon the shared cache volume while doing this, so concurrent jobs wait their turn instead of swapping the subtree out from under each other. Corpus entries that Go replays first are added to anNxbudget, so N mutated runs still happen. Usage is indocs/security-fuzz.md. - CI:
security-fuzz-fast(1000x) runs on merge requests.security-fuzz-deep(20sper target) runs on scheduled pipelines. Each branch caches its own corpus, falling back to the default branch's, so a crasher saved on one branch is never replayed on another. The jobs installutil-linuxforflock. The fuzz log and every package'stestdata/fuzzreproducers are kept as artifacts. - Solana test fix:
TestReportSolvencyConcurrentNoRaceno longer assumes the concurrent burst reaches every solvency boundary, sinceTryLockdrops overlapping attempts. It now checks that later passes at the same height catch up to the final boundary without going backwards.
Validation: Each target ran 1,000 local iterations; the integrated security-fuzz-fast CI job passed. This topic is also included in draft !5181 (closed). This MR will run its own CI against develop; review and merge coordination should avoid landing the same change twice.
Edited by Huginn Ai