harness-writing
Techniques for writing effective fuzzing harnesses across languages. Use when creating new fuzz targets or improving existing harness code.
npx skills add trailofbits/skills --skill harness-writing --agent claude-code
Same command for any agent — swap --agent for codex, cursor, copilot.
Weekly change comes from our own snapshots, not the repository page — it measures attention, not adoption.
What it does
Provides concrete guidance for writing fuzzing harnesses that feed fuzzers with structured input, route to the SUT, and handle edge cases gracefully. It emphasizes selecting entry points, starting with minimal harnesses, adding input validation, using helpers like FuzzedDataProvider, and applying patterns for interleaved fuzzing, structure-aware fuzzing, and deterministic behavior.
How it works
- Identifies entry points in codebases that accept external input or perform security-critical operations as targets for fuzzing.
- Recommends starting with a minimal harness in C/C++ or Rust demonstrating a basic LLVMFuzzerTestOneInput or fuzz_target setup.
- Advises adding input validation to reject inputs outside meaningful ranges while allowing malformed inputs to test harness robustness.
- Describes structuring inputs for typed data via techniques like casting or using FuzzedDataProvider, and provides code samples for both approaches.
- Covers various patterns: interleaved fuzzing across related operations, structure-aware fuzzing using Arbitrary in Rust, and using Protocol Buffers as an intermediate format for structured inputs.
- Encourages testing and iteration with metrics like code coverage, execution speed, and crash reproducibility.
- Presents practical harness rules to maintain determinism, avoid global state, prevent hangs, and ensure fast execution.
- Includes tool-specific guidance for libFuzzer and AFL++, with sample harness signatures, compilation commands, and integration tips.
When to use it
Use when creating a new fuzz target for the first time or when fuzz campaigns have low coverage or unreproducible crashes, and when the target API requires structured inputs or multiple related functions should be tested together.
What it can touch
- Mentions and uses the following tools and concepts explicitly: "LLVMFuzzerTestOneInput" (C/C++ harness entry), "fuzz_target!" (Rust harness macro), "FuzzedDataProvider" (helper for structured data), and protocols like Protocol Buffers as an intermediate format. It provides code blocks showing how to instantiate and use these components.
Caveats
- Emphasizes not to call exit() in harnesses, to maintain determinism and enable rapid iteration.
- Recommends avoiding heavy logging during fuzzing and resetting global state between iterations to improve reproducibility.
- Notes limitations of certain approaches (e.g., Arbitrary crate behavior and its limitations with reverse serialization).
# Writing Fuzzing Harnesses A fuzzing harness is the entrypoint function that receives random data from the fuzzer and routes it to your system under test (SUT). The quality of your harness directly determines which code paths get exercised and whether critical bugs are found. A poorly written harness can miss entire subsystems or produce non-reproducible crashes. ## Overview The harness is the bridge between the fuzzer's random byte generation and your application's API. It must parse raw bytes into meaningful inputs, call target functions, and handle edge cases gracefully. The most important part of any fuzzing setup is the harness—if written poorly, critical parts of your application may not be covered. ### Key Concepts | Concept | Description | |---------|-------------| | **Harness** | Function that receives fuzzer input and calls target code under test | | **SUT** | System Under Test—the code being fuzzed | | **Entry point** | Function signature required by the fuzzer (e.g., `LLVMFuzzerTestOneInput`) | | **FuzzedDataProvider** | Helper class for structured extraction of typed data from raw bytes | | **Determinism** | Property that ensures same input always produces same behavi
- Overview
- Key Concepts
- When to Apply
- Quick Reference
- Step-by-Step
- Step 1: Identify Entry Points
- Step 2: Write Minimal Harness
- Step 3: Add Input Validation
- Step 4: Structure the Input
- Step 5: Test and Iterate
- Common Patterns
- Pattern: Beyond Byte Arrays—Casting to Integers
- Pattern: FuzzedDataProvider for Complex Inputs
- Pattern: Interleaved Fuzzing
afl-fuzz -i seeds/ -o findings/ -- ./fuzz_target cargo fuzz init cargo fuzz add my_target cargo +nightly fuzz run my_target go-fuzz-build go-fuzz -bin=./mypackage-fuzz.zip -workdir=fuzz
What does the harness-writing skill do?
Techniques for writing effective fuzzing harnesses across languages. Use when creating new fuzz targets or improving existing harness code.
How do I install it?
Run `npx skills add trailofbits/skills --skill harness-writing --agent claude-code` — it drops the skill into your project so the agent can pick it up. Swap the --agent value for codex, cursor or copilot if you use one of those.
Where does this skill come from?
From trailofbits/skills, a repository with 6,426 stars. We read it straight from the repository tree rather than a submitted listing, so what you see here is what is actually published.
Is a popular skill a good skill?
Not necessarily. Stars measure attention, not adoption — a repository can trend for a week and be abandoned. That is why we show the weekly change from our own snapshots next to the total, instead of a single flattering number.
