| name | fuzz-harnesses |
| description | Use when the user asks to write, scaffold, run, or extend a Go-native fuzz harness for a parser/decoder/templater identified in a security-audit report — adding a target to targets.json, authoring a *_fuzz_test.go dropped into the audited repo's package, driving `make clone install build fuzz-<id>`, and triaging any crashers into follow-up findings. Offline only: no cluster, cloud creds, or service mocks. |
Fuzz Harnesses
Author and run offline Go-native fuzz tests against pure-function attack
surface (parsers, decoders, templaters, regex matchers) that a
secure-code-audit report has flagged as fuzz-worthy. Every harness is a
white-box *_fuzz_test.go copied into the target repo's own package tree so
it can reach unexported identifiers, driven by the Go 1.18+ native fuzzer
(go test -fuzz).
This skill wraps the existing tooling in this directory — targets.json,
Makefile, harnesses/<id>/*_fuzz_test.go, and the batch-plan docs. Read
README.md alongside this file for the full layout and design
notes.
Input
$ARGUMENTS is one of:
- A repository URL or
<org>/<repo> — scaffold new harnesses for that
repo. Look up its audit report under
analysis-results/findings/**/<repo>/<repo>-security-audit.{json,md} to
find recommended fuzz entry points (findings whose remediation mentions
fuzzing, or the report's remediation-roadmap "add fuzz harness" items).
Also check the refuted register —
<repo>-refuted-register.json alongside the audit report (emitted by
scripts/emit_triage_ledger_events.py) lists findings dismissed as
false positives; entries in fuzzable classes (parsers, decoders,
memory safety, injection) are PRIORITY targets, because a reproducing
crash overrides the FP assertion via evidence-class precedence
(fp_overridden). An FP is a falsifiable claim, not an exclusion.
- A finding ID (e.g.
KUBE_RBAC_PROXY-9cb7556-019) — scaffold a harness
for that specific finding's entry point.
- A target ID already in
targets.json — skip authoring; just
make clone install build fuzz-<id> and triage results.
- Nothing — run the whole current batch:
make clone install build then
make FUZZTIME=<duration> fuzz-all (or BATCH=<n> fuzz-all).
Preconditions
Working directory must be this skill's directory:
cd ai-security-harness/harnessing/fuzz-harnesses
Requires: go ≥ 1.22, jq, git, network access for make clone only.
Workflow
1. Locate or add the target
Check whether $ARGUMENTS already has an entry:
jq -r '.targets[] | select(.id=="<id>" or (.repo | contains("<repo>")))' targets.json
If absent, append a new object to .targets[] in targets.json:
{
"id": "<repo-name>",
"repo": "https://github.com/<org>/<repo>",
"module": "<go module path from go.mod>",
"commit": "<7-or-40-char SHA from the audit report's metadata.commit, or HEAD>",
"product_reach": <int — number of products shipping this repo, from repo-graph>,
"audit_ref": "<finding ID that recommended fuzzing>",
"batch": <next batch number>,
"harnesses": [
{
"file": "harnesses/<id>/<name>_fuzz_test.go",
"dest": "<pkg-path>/<name>_fuzz_test.go",
"fuzz": "Fuzz<Name>",
"pkg": "./<pkg-path>"
}
]
}
Optional per-target keys the Makefile honours: clone_alias (share a clone
across targets), workdir (subdir containing go.mod), goos (skip on other
host OS).
2. Author the harness
Create harnesses/<id>/<name>_fuzz_test.go. Rules:
package must match the target package (white-box, so unexported
identifiers are reachable). dest in targets.json places the file
in-tree.
- Seed corpus via
f.Add(...). Prefer real fixtures the repo already
ships (docs/samples/*.yaml, testdata/*). Otherwise hand-roll
minimal-valid + minimal-invalid + known-hostile (YAML anchor bomb, deeply
nested JSON, oversized varint, ../ path, %n format string) seeds.
- No network, cluster, or cloud at fuzz time. Substitute
k8s.io/client-go/dynamic/fake, discovery/fake, in-memory io.Reader,
synthetic net.Addr. If the entry point insists on I/O, drive the layer
below it.
- Prefer exported entry points; if the target is unexported, keep the
harness as thin as possible around it so upstream refactors surface as a
compile error, not a silent no-op.
- Header comment: drop-in
dest path, go test -fuzz invocation, target
file:line, and the crash classes you expect.
See harnesses/kube-rbac-proxy/config_fuzz_test.go for a reference harness
and BATCH-*.md for pattern guidance (sprig/text/template DoS,
strings.Split(...)[N] index panics, differential invariants).
3. Compile-check
make clone
make install build
make build must pass before fuzzing. A compile error means the pinned
commit's internals moved — re-scout the entry point and update the harness,
do not bump commit to HEAD just to make it compile.
4. Fuzz
make FUZZTIME=10m fuzz-<id>
make FUZZTIME=1h BATCH=<n> fuzz-all
Crashers land in
clones/<id>/<pkg>/testdata/fuzz/<FuzzName>/<hash>.
5. Triage crashers
For each crasher:
go test -run <FuzzName>/<hash> ./<pkg> to reproduce deterministically.
- Minimise the input (the Go fuzzer usually already has).
- Classify: panic (index-OOB, nil deref, type assertion), hang/timeout
(CWE-770 resource exhaustion), or invariant violation (differential).
- Copy the reproducer into
analysis-results/findings/**/<id>/fuzz-corpus/<FuzzName>/.
- File a follow-up finding — either amend the source
*-security-audit.json with a new finding whose evidence embeds the
reproducer and whose validation_status is confirmed, or open a new
finding via /file-security-defect. Use the campaign ID format
{REPO_SLUG}-{SHORTSHA}-{NNN} and set source_findings to the fuzz target's
audit_ref.
6. Report (batch mode)
When running a full batch, run-sweep.sh and gen-reports.sh produce a
per-batch summary under this directory. Update the relevant BATCH-<n>-PLAN.md
with results (hit / miss / compile-gap per target) so the next batch's
selection can learn from it.
Output
| Artefact | Path |
|---|
| New/updated manifest entry | targets.json |
| Harness source | harnesses/<id>/*_fuzz_test.go |
| Reproducers | analysis-results/findings/**/<id>/fuzz-corpus/<FuzzName>/<hash> |
| Crashers (git-ignored) | clones/<id>/<pkg>/testdata/fuzz/<FuzzName>/ |
| Follow-up finding | analysis-results/findings/**/<repo>-security-audit.json |
No JSON schema validation step — this skill produces Go source and manifest
edits, not audit reports. The report artefact is the amended finding in the
originating audit report.