Skip to main content

create-fuzzing

Use when the user asks to write, scaffold, run, or extend a fuzz harness for a parser/decoder/templater identified in a security-audit report — Go-native by default, plus Python (atheris), JavaScript/TypeScript (Jazzer.js), Rust (cargo-fuzz), and Java (jazzer, manual run) via the language field in targets.json and templates under harnesses/_templates/. Adds a target to targets.json, authors a harness dropped into the audited repo's tree, drives `make clone install build fuzz-<id>`, and triages any crashers into follow-up findings. Offline only: no cluster, cloud creds, or service mocks.

معلومات المصدر

المستودع
openshift/traust
آخر نشاط في المصدر
٨ سبتمبر ٢٠٢٦ في ١٩:٣٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٤
التفرعات
٨

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
15 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
create-fuzzing
description
Use when the user asks to write, scaffold, run, or extend a fuzz harness for a parser/decoder/templater identified in a security-audit report — Go-native by default, plus Python (atheris), JavaScript/TypeScript (Jazzer.js), Rust (cargo-fuzz), and Java (jazzer, manual run) via the language field in targets.json and templates under harnesses/_templates/. Adds a target to targets.json, authors a harness dropped into the audited repo's tree, drives `make clone install build fuzz-<id>`, and triages any crashers into follow-up findings. Offline only: no cluster, cloud creds, or service mocks.
metadata
{"harness.tier":"primary"}
# Fuzz Harnesses > **Paths.** `analysis-results/…` and `progress-tracker/…` in this skill are the > default workspace layout. They resolve through `locations.yaml` in > `$TRAUST_CONFIG_HOME` (`docs/setup.md`, Storage locations); substitute your > configured roots. 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](README.md) alongside this file for the full layout and design notes. ## Input `$ARGUMENTS` is one of: 1. **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 python3 -m traust.cli ledger emit-triage) 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. 2. **A finding ID** (e.g. `KUBE_RBAC_PROXY-9cb7556-019`) — scaffold a harness for that specific finding's entry point. 2b. **An impact-analysis artifact** (`analysis-results/impact/<cve>-impact-analysis.json`, from `/impact-analysis`) — scaffold harnesses for the repos classified `affected`. This is the assurance-promotion path: `affected` is call-graph reachability (machine static, evidence class 3); a reproducing input is execution evidence (class 1) that flips the finding to `confirmed` in the disposition ledger. Target the entry point from the repo's `evidence.govulncheck_trace` — the first in-repo frame is the natural harness entry — and seed the corpus with advisory-shaped input (`metadata.feature_description` names the vulnerable capability). Set the target's `audit_ref` to the CVE ID. Prioritize by severity and by `attacker_influence: plausible` where triage has judged the trace. 3. **A target ID already in `targets.json`** — skip authoring; just `make clone install build fuzz-<id>` and triage results. 4. **Nothing** — run the whole current batch: `make clone install build` then `make FUZZTIME=<duration> fuzz-all` (or `BATCH=<n> fuzz-all`). ## Non-Go languages (C4) Go stays the default (`language` absent = `go`; nothing changes for existing targets). For other ecosystems, set `"language"` on the target and author from the matching template in `harnesses/_templates/`: | language | engine | template | run | |---|---|---|---| | `python` | atheris (Apache-2.0) | `python_fuzz.py` | `make fuzz-<id>` — per-clone `.fuzzvenv`, FUZZTIME-bounded | | `javascript` | Jazzer.js (Apache-2.0) | `js_fuzz.js` | `make fuzz-<id>` — `npx jazzer`, FUZZTIME-bounded | | `rust` | cargo-fuzz + libFuzzer | `rust_fuzz.rs` | `make fuzz-<id>` — requires nightly toolchain; dest under `fuzz/fuzz_targets/` | | `java` | jazzer (JVM), **pinned v0.30.0** (sha256-verified download; Apache-2.0 verified at the tag — docs/external-dependencies.md) | `JavaFuzz.java` | `make fuzz-<id>` — builds the target (maven `package` or gradle `assemble`), assembles the classpath, runs the pinned jazzer against the manifest's `.fuzz` class, FUZZTIME-bounded | Same rules as Go targets: harnesses live in `analysis-results/fuzz-harnesses/<id>/` and are copied into the clone by `make install` (dest inside the target tree so imports resolve); expected parse errors are swallowed in the harness — crashes, hangs, and memory blowups are the findings; crashers are triaged identically (reproducer + follow-up finding + rollup entry, with the target's `language` carried through). Engine licenses are verified in `docs/external-dependencies.md`; the engines are dependencies of the *generated harnesses in target repos*, never of this repository. ## Preconditions Working directory must be this skill's directory: ```bash cd traust/harnessing/6-fuzz/create-fuzzing ``` 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: ```bash jq -r '.targets[] | select(.id=="<id>" or (.repo | contains("<repo>")))' targets.json ``` If **absent**, append a new object to `.targets[]` in `targets.json`: ```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": "<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 `analysis-results/fuzz-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 `analysis-results/fuzz-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 ```bash make clone # shallow-fetch repos at pinned commits (idempotent) make install build # copy harnesses in-tree and go test -run '^$' compile-check ``` `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 ```bash make FUZZTIME=10m fuzz-<id> # one target make FUZZTIME=1h BATCH=<n> fuzz-all # a whole batch ``` Crashers land in `clones/<id>/<pkg>/testdata/fuzz/<FuzzName>/<hash>`. ### 5. Triage crashers For each crasher: 1. `go test -run <FuzzName>/<hash> ./<pkg>` to reproduce deterministically. 2. Minimise the input (the Go fuzzer usually already has). 3. Classify: panic (index-OOB, nil deref, type assertion), hang/timeout (CWE-770 resource exhaustion), or invariant violation (differential). 4. Copy the reproducer into `analysis-results/findings/**/<id>/fuzz-corpus/<FuzzName>/`. 5. **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. **Record it in the disposition ledger.** A crasher that only exists as prose in a batch summary is not recorded — the ledger is the register of what we know about a finding, and for months it held none of these. ```bash python3 harnessing/6-fuzz/create-fuzzing/scripts/emit_fuzz_events.py # dry run python3 harnessing/6-fuzz/create-fuzzing/scripts/emit_fuzz_events.py --apply ``` One event per crasher: `source.type: fuzz_report`, the bug record as `source.ref`, the reproducer directory in `evidence_refs`. Where the target's `audit_ref` is a clean `FIND-NNN` the event attaches to that finding; otherwise it carries a new one. Emits under gate A15 — the baseline audit report is never written — and is idempotent by `event_id`. `fuzz_report` is evidence class 1 because the triggering input is kept, so the claim is replayable. The converse is the part that gets misread: a fuzz run that finds nothing emits NOTHING here. Absence of a crash is not evidence of correctness. A repo audited under several products has one layer per product. The tool refuses to guess which and reports the ambiguity; `--all-layers` records the crasher under every product that ships the code. ### 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 | `analysis-results/fuzz-harnesses/<id>/*_fuzz_test.go` — the CORPUS, not this repo: a harness is test code written ABOUT an audited repository, the same category as a finding about it. `file:` in `targets.json` is relative to that root (`HARNESSES` in the Makefile) | | Reproducers | `analysis-results/findings/**/<id>/fuzz-corpus/<FuzzName>/<hash>` | | Crashers (git-ignored) | `clones/<id>/<pkg>/testdata/fuzz/<FuzzName>/` | | Follow-up finding | carried on a ledger event in `analysis-results/findings/**/<repo>-findings-layer.json` (gate A15 — never the baseline) | | Campaign summary + rollup (via `build_fuzz_rollup.py`) | `analysis-results/FUZZ-CAMPAIGN-SUMMARY.{md,json}` + `FUZZ-FINDINGS-ROLLUP.md` — the `.json` is the machine-readable sidecar dashboards consume; all three also published to `progress-tracker/metrics/dashboards/fuzz/` | No JSON schema validation step — this skill produces Go source and manifest edits, not audit reports. The report artefact is the follow-up finding carried on its ledger event; the originating audit report is not modified (gate A15). ## Integrations - **Inputs:** audit reports' fuzz-worthy entry points, refuted registers (FP falsification targets), and `/impact-analysis` artifacts (form 2b — the class-3→class-1 promotion path). - **Outputs consumed by:** the event-carried follow-up finding (with reproducer evidence) flows through `/track-findings` as execution evidence; `FUZZ-CAMPAIGN-SUMMARY.json` feeds `/validation-fuzz-dashboard`; crashers override FP assertions via evidence-class precedence in the disposition ledger. ## Spend declaration (calibration tuple) After this skill's report/artifact is written, declare the run's spend against the target so `estimate_scan` can calibrate per-skill cost models (contract: docs/model-routing.md; analysis: progress-tracker/metrics/estimate-calibration-analysis.md §F5): ```bash python3 -m traust.cli registry models spend --skill create-fuzzing \ --model <resolved model id> [--tokens-in <N>] [--tokens-out <N>] \ --repo <target-slug> --loc <target size, if known> [--batch <batch-id>] ``` Token counts are OPTIONAL and best-effort: pass them when the orchestrator has them (Task results carry per-subagent usage), otherwise omit them — an agent cannot observe its own usage mid-run. **This row is a routing marker, not a cost claim**; actual per-lane cost is attributed from session transcripts by python3 -m traust.cli metrics attribute-spend. Never skip the row: an unattributed run is a calibration gap.
عرض على GitHub