Official agent skill

Libfuzzer

by trailofbits in trailofbits/skills

Sets up and runs libFuzzer, the coverage-guided fuzzer built into LLVM, on C/C++ code that compiles with Clang.

OfficialCC-BY-SA-4.0Auto-check passedSecurity

Install Libfuzzer

skills CLI
$ npx skills add trailofbits/skills --skill libfuzzer -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install trailofbits/skills libfuzzer --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/testing-handbook-skills/skills/libfuzzer .claude/skills/libfuzzer && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
libfuzzer
GitHub stars
7.4k
Token cost
~6.1k tokens
SKILL.md length
1,701 words
Files
3 (incl. assets)
Skills in repo
79
Repo updated
First seen
Licence
CC-BY-SA-4.0

At a glance

Sets up and runs libFuzzer, the coverage-guided fuzzer built into LLVM, on C/C++ code that compiles with Clang.

  • Works in 2 steps: Build the library with fuzzing… → Link the static library with your harness
  • Debugging an LLVMFuzzerTestOneInput harness
  • SKILL.md covers When to Use, Quick Start, Installation and Writing a Harness, plus 3 more sections
  • Calls curl, apt and make; reaches raw.githubusercontent.com and downloads.sourceforge.net

What it does

Libfuzzer is an agent skill from trailofbits/skills, published by the product's own GitHub organization. Sets up and runs libFuzzer, the coverage-guided fuzzer built into LLVM, on C/C++ code that compiles with Clang. Covers harness structure, -fsanitize=fuzzer builds, corpus and dictionary management, sanitizer integration, and campaign triage. Use when writing or debugging an LLVMFuzzerTestOneInput harness, starting fuzzing on a C/C++ library, choosing between libFuzzer and AFL++, or working out why a libFuzzer run finds nothing.

Its SKILL.md is about 6.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 4 other files, including assets (for example `agents/openai.yaml`).

It sits in Security, covering Fuzzing. It works with C++. The repository describes itself as: Trail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows. The licence is CC-BY-SA-4.0.

When your agent uses it

  • Debugging an LLVMFuzzerTestOneInput harness
  • Starting fuzzing on a C/C++ library
  • Choosing between libFuzzer and AFL++
  • Working out why a libFuzzer run finds nothing

Example prompts

  • “/libfuzzer”

Workflow steps

2 steps, taken from the first numbered list in SKILL.md.

  1. Build the library with fuzzing instrumentation
  2. Link the static library with your harness

What it can do on your machine

Read from SKILL.md and the folder at commit 82fe822. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • curl
    • apt
    • make
    • cmake
    • brew

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • raw.githubusercontent.com
    • downloads.sourceforge.net

    Also links to:

    • github.com
    • learn.microsoft.com
    • llvm.org
    • clang.llvm.org

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Libfuzzer loads about 6.1k tokens when it runs. Until then it costs about 110 tokens; SKILL.md has 1,701 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~110
When it runs · the whole SKILL.md, loaded when a task matches
~6.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from trailofbits/skills at commit 82fe822, republished under its CC-BY-SA-4.0 licence (© trailofbits). 1,701 words, ~6,059 tokens.

Download SKILL.mdSave it as .claude/skills/libfuzzer/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
libfuzzer
description
Sets up and runs libFuzzer, the coverage-guided fuzzer built into LLVM, on C/C++ code that compiles with Clang. Covers harness structure, -fsanitize=fuzzer builds, corpus and dictionary management, sanitizer integration, and campaign triage. Use when writing or debugging an LLVMFuzzerTestOneInput harness, starting fuzzing on a C/C++ library, choosing between libFuzzer and AFL++, or working out why a libFuzzer run finds nothing.
type
fuzzer

libFuzzer

libFuzzer is an in-process, coverage-guided fuzzer that is part of the LLVM project. It's the recommended starting point for fuzzing C/C++ projects due to its simplicity and integration with the LLVM toolchain. While libFuzzer has been in maintenance-only mode since late 2022, it is easier to install and use than its alternatives, has wide support, and will be maintained for the foreseeable future.

When to Use

FuzzerBest ForComplexity
libFuzzerQuick setup, single-project fuzzingLow
AFL++Multi-core fuzzing, diverse mutationsMedium
LibAFLCustom fuzzers, research projectsHigh
HonggfuzzHardware-based coverageMedium

Choose libFuzzer when:

  • You need a simple, quick setup for C/C++ code
  • Project uses Clang for compilation
  • Single-core fuzzing is sufficient initially
  • Transitioning to AFL++ later is an option (harnesses are compatible)

Note: Fuzzing harnesses written for libFuzzer are compatible with AFL++, making it easy to transition if you need more advanced features like better multi-core support.

Quick Start

c++
#include <stdint.h>
#include <stddef.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    // Validate input if needed
    if (size < 1) return 0;

    // Call your target function with fuzzer-provided data
    my_target_function(data, size);

    return 0;
}

Compile and run:

bash
clang++ -fsanitize=fuzzer,address -g -O2 harness.cc target.cc -o fuzz
mkdir corpus/
./fuzz corpus/

Installation

Prerequisites
  • LLVM/Clang compiler (includes libFuzzer)
  • LLVM tools for coverage analysis (optional)
Linux (Ubuntu/Debian)
bash
apt install clang llvm

For the latest LLVM version:

bash
# Add LLVM repository from apt.llvm.org
# Then install specific version, e.g.:
apt install clang-18 llvm-18
macOS
bash
# Using Homebrew
brew install llvm

# Or using Nix
nix-env -i clang
Windows

Install Clang through Visual Studio. Refer to Microsoft's documentation for setup instructions.

Recommendation: If possible, fuzz on a local x86_64 VM or rent one on DigitalOcean, AWS, or Hetzner. Linux provides the best support for libFuzzer.

Verification
bash
clang++ --version
# Should show LLVM version information

Writing a Harness

Harness Structure

The harness is the entry point for the fuzzer. libFuzzer calls the LLVMFuzzerTestOneInput function repeatedly with different inputs.

c++
#include <stdint.h>
#include <stddef.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    // 1. Optional: Validate input size
    if (size < MIN_REQUIRED_SIZE) {
        return 0;  // Reject inputs that are too small
    }

    // 2. Optional: Convert raw bytes to structured data
    // Example: Parse two integers from byte array
    if (size >= 2 * sizeof(uint32_t)) {
        uint32_t a = *(uint32_t*)(data);
        uint32_t b = *(uint32_t*)(data + sizeof(uint32_t));
        my_function(a, b);
    }

    // 3. Call target function
    target_function(data, size);

    // 4. Always return 0 (non-zero reserved for future use)
    return 0;
}
Harness Rules
DoDon't
Handle all input types (empty, huge, malformed)Call exit() - stops fuzzing process
Join all threads before returningLeave threads running
Keep harness fast and simpleAdd excessive logging or complexity
Maintain determinismUse random number generators or read /dev/random
Reset global state between runsRely on state from previous executions
Use narrow, focused targetsMix unrelated data formats (PNG + TCP) in one harness

Rationale:

  • Speed matters: Aim for 100s-1000s executions per second per core
  • Reproducibility: Crashes must be reproducible after fuzzing completes
  • Isolation: Each execution should be independent
Using FuzzedDataProvider for Complex Inputs

For complex inputs (strings, multiple parameters), use the FuzzedDataProvider helper:

c++
#include <stdint.h>
#include <stddef.h>
#include "FuzzedDataProvider.h"  // From LLVM project

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    FuzzedDataProvider fuzzed_data(data, size);

    // Extract structured data
    size_t allocation_size = fuzzed_data.ConsumeIntegral<size_t>();
    std::vector<char> str1 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
    std::vector<char> str2 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);

    // Call target with extracted data
    char* result = concat(&str1[0], str1.size(), &str2[0], str2.size(), allocation_size);
    if (result != NULL) {
        free(result);
    }

    return 0;
}

Download FuzzedDataProvider.h from the LLVM repository.

Interleaved Fuzzing

Use a single harness to test multiple related functions:

c++
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    if (size < 1 + 2 * sizeof(int32_t)) {
        return 0;
    }

    uint8_t mode = data[0];
    int32_t numbers[2];
    memcpy(numbers, data + 1, 2 * sizeof(int32_t));

    // Select function based on first byte
    switch (mode % 4) {
        case 0: add(numbers[0], numbers[1]); break;
        case 1: subtract(numbers[0], numbers[1]); break;
        case 2: multiply(numbers[0], numbers[1]); break;
        case 3: divide(numbers[0], numbers[1]); break;
    }

    return 0;
}

See Also: For detailed harness writing techniques, patterns for handling complex inputs, structure-aware fuzzing, and protobuf-based fuzzing, see the fuzz-harness-writing technique skill.

Compilation

Basic Compilation

The key flag is -fsanitize=fuzzer, which:

  • Links the libFuzzer runtime (provides main function)
  • Enables SanitizerCoverage instrumentation for coverage tracking
  • Disables built-in functions like memcmp
bash
clang++ -fsanitize=fuzzer -g -O2 harness.cc target.cc -o fuzz

Flags explained:

  • -fsanitize=fuzzer: Enable libFuzzer
  • -g: Add debug symbols (helpful for crash analysis)
  • -O2: Production-level optimizations (recommended for fuzzing)
  • -DNO_MAIN: Define macro if your code has a main function
With Sanitizers

AddressSanitizer (recommended):

bash
clang++ -fsanitize=fuzzer,address -g -O2 -U_FORTIFY_SOURCE harness.cc target.cc -o fuzz

Multiple sanitizers:

bash
clang++ -fsanitize=fuzzer,address,undefined -g -O2 harness.cc target.cc -o fuzz

See Also: For detailed sanitizer configuration, common issues, ASAN_OPTIONS flags, and advanced sanitizer usage, see the address-sanitizer and undefined-behavior-sanitizer technique skills.

Build Flags
FlagPurpose
-fsanitize=fuzzerEnable libFuzzer runtime and instrumentation
-fsanitize=addressEnable AddressSanitizer (memory error detection)
-fsanitize=undefinedEnable UndefinedBehaviorSanitizer
-fsanitize=fuzzer-no-linkInstrument without linking fuzzer (for libraries)
-gInclude debug symbols
-O2Production optimization level
-U_FORTIFY_SOURCEDisable fortification (can interfere with ASan)
Building Static Libraries

For projects that produce static libraries:

  1. Build the library with fuzzing instrumentation:
bash
export CC=clang CFLAGS="-fsanitize=fuzzer-no-link -fsanitize=address"
export CXX=clang++ CXXFLAGS="$CFLAGS"
./configure --enable-shared=no
make
  1. Link the static library with your harness:
bash
clang++ -fsanitize=fuzzer -fsanitize=address harness.cc libmylib.a -o fuzz
CMake Integration
cmake
project(FuzzTarget)
cmake_minimum_required(VERSION 3.0)

add_executable(fuzz main.cc harness.cc)
target_compile_definitions(fuzz PRIVATE NO_MAIN=1)
target_compile_options(fuzz PRIVATE -g -O2 -fsanitize=fuzzer -fsanitize=address)
target_link_libraries(fuzz -fsanitize=fuzzer -fsanitize=address)

Build with:

bash
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .
cmake --build .

Corpus Management

Creating Initial Corpus

Create a directory for the corpus (can start empty):

bash
mkdir corpus/

Optional but recommended: Provide seed inputs (valid example files):

bash
# For a PNG parser:
cp examples/*.png corpus/

# For a protocol parser:
cp test_packets/*.bin corpus/

Benefits of seed inputs:

  • Fuzzer doesn't start from scratch
  • Reaches valid code paths faster
  • Significantly improves effectiveness
Corpus Structure

The corpus directory contains:

  • Input files that trigger unique code paths
  • Minimized versions (libFuzzer automatically minimizes)
  • Named by content hash (e.g., a9993e364706816aba3e25717850c26c9cd0d89d)
Corpus Minimization

libFuzzer automatically minimizes corpus entries during fuzzing. To explicitly minimize:

bash
mkdir minimized_corpus/
./fuzz -merge=1 minimized_corpus/ corpus/

This creates a deduplicated, minimized corpus in minimized_corpus/.

See Also: For corpus creation strategies, seed selection, format-specific corpus building, and corpus maintenance, see the fuzzing-corpus technique skill.

Running Campaigns

Basic Run
bash
./fuzz corpus/

This runs until a crash is found or you stop it (Ctrl+C).

bash
./fuzz -fork=1 -ignore_crashes=1 corpus/

The -fork and -ignore_crashes flags (experimental but widely used) allow fuzzing to continue after finding crashes.

Common Options

Control input size:

bash
./fuzz -max_len=4000 corpus/

Rule of thumb: 2x the size of minimal realistic input.

Set timeout:

bash
./fuzz -timeout=2 corpus/

Abort test cases that run longer than 2 seconds.

Use a dictionary:

bash
./fuzz -dict=./format.dict corpus/

Close stdout/stderr (speed up fuzzing):

bash
./fuzz -close_fd_mask=3 corpus/

See all options:

bash
./fuzz -help=1
Multi-Core Fuzzing

Option 1: Jobs and workers (recommended):

bash
./fuzz -jobs=4 -workers=4 -fork=1 -ignore_crashes=1 corpus/
  • -jobs=4: Run 4 sequential campaigns
  • -workers=4: Process jobs in parallel with 4 processes
  • Test cases are shared between jobs

Option 2: Fork mode:

bash
./fuzz -fork=4 -ignore_crashes=1 corpus/

Note: For serious multi-core fuzzing, consider switching to AFL++, Honggfuzz, or LibAFL.

Re-executing Test Cases

Re-run a single crash:

bash
./fuzz ./crash-a9993e364706816aba3e25717850c26c9cd0d89d

Test all inputs in a directory without fuzzing:

bash
./fuzz -runs=0 corpus/
Interpreting Output

When fuzzing runs, you'll see statistics like:

INFO: Seed: 3517090860
INFO: Loaded 1 modules (9 inline 8-bit counters)
#2      INITED cov: 3 ft: 4 corp: 1/1b exec/s: 0 rss: 26Mb
#57     NEW    cov: 4 ft: 5 corp: 2/4b lim: 4 exec/s: 0 rss: 26Mb
OutputMeaning
INITEDFuzzing initialized
NEWNew coverage found, added to corpus
REDUCEInput minimized while keeping coverage
cov: NNumber of coverage edges hit
corp: X/YbCorpus size: X entries, Y total bytes
exec/s: NExecutions per second
rss: NMbResident memory usage

On crash:

==11672== ERROR: libFuzzer: deadly signal
artifact_prefix='./'; Test unit written to ./crash-a9993e364706816aba3e25717850c26c9cd0d89d
0x61,0x62,0x63,
abc
Base64: YWJj

The crash is saved to ./crash-<hash> with the input shown in hex, UTF-8, and Base64.

Reproducibility: Use -seed=<value> to reproduce a fuzzing campaign (single-core only).

Fuzzing Dictionary

Dictionaries help the fuzzer discover interesting inputs faster by providing hints about the input format.

Dictionary Format

Create a text file with quoted strings (one per line):

conf
# Lines starting with '#' are comments

# Magic bytes
magic="\x89PNG"
magic2="IEND"

# Keywords
"GET"
"POST"
"Content-Type"

# Hex sequences
delimiter="\xFF\xD8\xFF"
Using a Dictionary
bash
./fuzz -dict=./format.dict corpus/
Generating a Dictionary

From header files:

bash
grep -o '".*"' header.h > header.dict

From man pages:

bash
man curl | grep -oP '^\s*(--|-)\K\S+' | sed 's/[,.]$//' | sed 's/^/"&/; s/$/&"/' | sort -u > man.dict

From binary strings:

bash
strings ./binary | sed 's/^/"&/; s/$/&"/' > strings.dict

Using LLMs: Ask ChatGPT or similar to generate a dictionary for your format (e.g., "Generate a libFuzzer dictionary for a JSON parser").

See Also: For advanced dictionary generation, format-specific dictionaries, and dictionary optimization strategies, see the fuzzing-dictionaries technique skill.

Coverage Analysis

While libFuzzer shows basic coverage stats (cov: N), detailed coverage analysis requires additional tools.

Source-Based Coverage

1. Recompile with coverage instrumentation:

bash
clang++ -fsanitize=fuzzer -fprofile-instr-generate -fcoverage-mapping harness.cc target.cc -o fuzz

2. Run fuzzer to collect coverage:

bash
LLVM_PROFILE_FILE="coverage-%p.profraw" ./fuzz -runs=10000 corpus/

3. Merge coverage data:

bash
llvm-profdata merge -sparse coverage-*.profraw -o coverage.profdata

4. Generate coverage report:

bash
llvm-cov show ./fuzz -instr-profile=coverage.profdata

5. Generate HTML report:

bash
llvm-cov show ./fuzz -instr-profile=coverage.profdata -format=html > coverage.html
Improving Coverage

Tips:

  • Provide better seed inputs in corpus
  • Use dictionaries for format-aware fuzzing
  • Check if harness properly exercises target
  • Consider structure-aware fuzzing for complex formats
  • Run longer campaigns (days/weeks)

See Also: For detailed coverage analysis techniques, identifying coverage gaps, systematic coverage improvement, and comparing coverage across fuzzers, see the coverage-analysis technique skill.

Show full SKILL.md (676 more words)Show less

Sanitizer Integration

AddressSanitizer (ASan)

ASan detects memory errors like buffer overflows and use-after-free bugs. Highly recommended for fuzzing.

Enable ASan:

bash
clang++ -fsanitize=fuzzer,address -g -O2 -U_FORTIFY_SOURCE harness.cc target.cc -o fuzz

Example ASan output:

==1276163==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000c4ab1
WRITE of size 1 at 0x6020000c4ab1 thread T0
    #0 0x55555568631a in check_buf(char*, unsigned long) main.cc:13:25
    #1 0x5555556860bf in LLVMFuzzerTestOneInput harness.cc:7:3

Configure ASan with environment variables:

bash
ASAN_OPTIONS=verbosity=1:abort_on_error=1 ./fuzz corpus/

Important flags:

  • verbosity=1: Show ASan is active
  • detect_leaks=0: Disable leak detection (leaks reported at end)
  • abort_on_error=1: Call abort() instead of _exit() on errors

Drawbacks:

  • 2-4x slowdown
  • Requires ~20TB virtual memory (disable memory limits: -rss_limit_mb=0)
  • Best supported on Linux

See Also: For comprehensive ASan configuration, common pitfalls, symbolization, and combining with other sanitizers, see the address-sanitizer technique skill.

UndefinedBehaviorSanitizer (UBSan)

UBSan detects undefined behavior like integer overflow, null pointer dereference, etc.

Enable UBSan:

bash
clang++ -fsanitize=fuzzer,undefined -g -O2 harness.cc target.cc -o fuzz

Combine with ASan:

bash
clang++ -fsanitize=fuzzer,address,undefined -g -O2 harness.cc target.cc -o fuzz
MemorySanitizer (MSan)

MSan detects uninitialized memory reads. More complex to use (requires rebuilding all dependencies).

bash
clang++ -fsanitize=fuzzer,memory -g -O2 harness.cc target.cc -o fuzz
Common Sanitizer Issues
IssueSolution
ASan slows fuzzing too muchUse -fsanitize-recover=address for non-fatal errors
Out of memorySet ASAN_OPTIONS=rss_limit_mb=0 or -rss_limit_mb=0
Stack exhaustionIncrease stack size: ASAN_OPTIONS=stack_size=8388608
False positives with _FORTIFY_SOURCEUse -U_FORTIFY_SOURCE flag
MSan reports in dependenciesRebuild all dependencies with -fsanitize=memory

Real-World Examples

Example 1: Fuzzing libpng

libpng is a widely-used library for reading/writing PNG images. Bugs can lead to security issues.

1. Get source code:

bash
curl -L -O https://downloads.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
tar xf libpng-1.6.37.tar.xz
cd libpng-1.6.37/

2. Install dependencies:

bash
apt install zlib1g-dev

3. Compile with fuzzing instrumentation:

bash
export CC=clang CFLAGS="-fsanitize=fuzzer-no-link -fsanitize=address"
export CXX=clang++ CXXFLAGS="$CFLAGS"
./configure --enable-shared=no
make

4. Get a harness (or write your own):

bash
curl -O https://raw.githubusercontent.com/glennrp/libpng/f8e5fa92b0e37ab597616f554bee254157998227/contrib/oss-fuzz/libpng_read_fuzzer.cc

5. Prepare corpus and dictionary:

bash
mkdir corpus/
curl -o corpus/input.png https://raw.githubusercontent.com/glennrp/libpng/acfd50ae0ba3198ad734e5d4dec2b05341e50924/contrib/pngsuite/iftp1n3p08.png
curl -O https://raw.githubusercontent.com/glennrp/libpng/2fff013a6935967960a5ae626fc21432807933dd/contrib/oss-fuzz/png.dict

6. Link and compile fuzzer:

bash
clang++ -fsanitize=fuzzer -fsanitize=address libpng_read_fuzzer.cc .libs/libpng16.a -lz -o fuzz

7. Run fuzzing campaign:

bash
./fuzz -close_fd_mask=3 -dict=./png.dict corpus/
Example 2: Simple Division Bug

Harness that finds a division-by-zero bug:

c++
#include <stdint.h>
#include <stddef.h>

double divide(uint32_t numerator, uint32_t denominator) {
    // Bug: No check if denominator is zero
    return numerator / denominator;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    if(size != 2 * sizeof(uint32_t)) {
        return 0;
    }

    uint32_t numerator = *(uint32_t*)(data);
    uint32_t denominator = *(uint32_t*)(data + sizeof(uint32_t));

    divide(numerator, denominator);

    return 0;
}

Compile and fuzz:

bash
clang++ -fsanitize=fuzzer harness.cc -o fuzz
./fuzz

The fuzzer will quickly find inputs causing a crash.

Advanced Usage

Tips and Tricks
TipWhy It Helps
Start with single-core, switch to AFL++ for multi-corelibFuzzer harnesses work with AFL++
Use dictionaries for structured formats10-100x faster bug discovery
Close file descriptors with -close_fd_mask=3Speed boost if SUT writes output
Set reasonable -max_lenPrevents wasted time on huge inputs
Run for days/weeks, not minutesCoverage plateaus take time to break
Use seed corpus from test suitesStarts fuzzing from valid inputs
Structure-Aware Fuzzing

For highly structured inputs (e.g., complex protocols, file formats), use libprotobuf-mutator:

  • Define input structure using Protocol Buffers
  • libFuzzer mutates protobuf messages (structure-preserving mutations)
  • Harness converts protobuf to native format

See structure-aware fuzzing documentation for details.

Custom Mutators

libFuzzer allows custom mutators for specialized fuzzing:

c++
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
                                          size_t MaxSize, unsigned int Seed) {
    // Custom mutation logic
    return new_size;
}

extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
                                            const uint8_t *Data2, size_t Size2,
                                            uint8_t *Out, size_t MaxOutSize,
                                            unsigned int Seed) {
    // Custom crossover logic
    return new_size;
}
Performance Tuning
SettingImpact
-close_fd_mask=3Closes stdout/stderr, speeds up fuzzing
-max_len=<reasonable_size>Avoids wasting time on huge inputs
-timeout=<seconds>Detects hangs, prevents stuck executions
Disable ASan for baseline2-4x speed boost (but misses memory bugs)
Use -jobs and -workersLimited multi-core support
Run on LinuxBest platform support and performance

Troubleshooting

ProblemCauseSolution
No crashes found after hoursPoor corpus, low coverageAdd seed inputs, use dictionary, check harness
Very slow executions/sec (<100)Target too complex, excessive loggingOptimize target, use -close_fd_mask=3, reduce logging
Out of memoryASan's 20TB virtual memorySet -rss_limit_mb=0 to disable RSS limit
Fuzzer stops after first crashDefault behaviorUse -fork=1 -ignore_crashes=1 to continue
Can't reproduce crashNon-determinism in harness/targetRemove random number generation, global state
Linking errors with -fsanitize=fuzzerMissing libFuzzer runtimeEnsure using Clang, check LLVM installation
GCC project won't compile with ClangGCC-specific codeSwitch to AFL++ with gcc_plugin instead
Coverage not improvingCorpus plateauRun longer, add dictionary, improve seeds, check coverage report
Crashes but ASan doesn't triggerMemory error not detected without ASanRecompile with -fsanitize=address
Technique Skills
SkillUse Case
fuzz-harness-writingDetailed guidance on writing effective harnesses, structure-aware fuzzing, and FuzzedDataProvider usage
address-sanitizerMemory error detection configuration, ASAN_OPTIONS, and troubleshooting
undefined-behavior-sanitizerDetecting undefined behavior during fuzzing
coverage-analysisMeasuring fuzzing effectiveness and identifying untested code paths
fuzzing-corpusBuilding and managing seed corpora, corpus minimization strategies
fuzzing-dictionariesCreating format-specific dictionaries for faster bug discovery
SkillWhen to Consider
aflppWhen you need serious multi-core fuzzing, or when libFuzzer coverage plateaus
honggfuzzWhen you want hardware-based coverage feedback on Linux
libaflWhen building custom fuzzers or conducting fuzzing research

Resources

Official Documentation
Advanced Topics
Example Projects

© trailofbits, CC-BY-SA-4.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files (assets) in plugins/testing-handbook-skills/skills/libfuzzer of trailofbits/skills.

  • SKILL.md
  • agents/openai.yaml
  • assets/trail-of-bits-mark.svg

Open the folder on GitHubat commit 82fe822

Compare with similar skills

Libfuzzer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Libfuzzer compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Libfuzzer this skilltrailofbits/skills7.4k—~6.1kAutomated safety check: PassCC-BY-SA-4.0
Harness Design Fuzzingprovos/ironcurtain613—~5.7kAutomated safety check: PassApache-2.0
ClusterfuzzliteInternationalColorConsortium/iccDEV183—~1.5kAutomated safety check: PassBSD-3-Clause
Audit Native Memory Safetycyberful/cyberful134—~829Automated safety check: PassAGPL-3.0
Fuzzingmohitmishra786/low-level-dev-skills253—~2.1kAutomated safety check: PassMIT
Fizzpashov/skills1.2k2 repos~11kAutomated safety check: PassMIT

Similar skills

  • Harness Design Fuzzing

    provos/ironcurtain

    Reference vocabulary for designing instrumented harnesses that drive vulnerability discovery — design classes (trigger-driven vs coverage-driven), tiered scope (T1 isolated function / T2…

    613 GitHub stars~5.7k tokensUpdated today
    SecurityAuto-check passed
  • Clusterfuzzlite

    InternationalColorConsortium/iccDEV

    Build, test, or update the iccDEV ClusterFuzzLite libFuzzer integration across ASan, UBSan, and MSan.

    183 GitHub stars~1.5k tokensUpdated today
    SecurityAuto-check passed
  • Audit C, C++, unsafe Rust, native extensions, parsers, codecs, FFI boundaries, and systems code for memory corruption and low-level exploitation risk.

    134 GitHub stars~829 tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Fuzzing

    mohitmishra786/low-level-dev-skills

    Fuzzing skill for automated input-driven bug finding in C/C++.

    253 GitHub stars~2.1k tokensUpdated 3 mo ago
    SecurityAuto-check passed
  • Fizz

    pashov/skills

    Generate Echidna/Medusa-compatible Solidity fuzz suites from Foundry or Hardhat projects.

    1.2k GitHub starsUsed in 2 repos~11k tokens
    SecurityAuto-check passed
  • Official

    Finds and fixes out-of-range output writes in ONNX Runtime operator shape-inference functions where a getNumOutputs guard admits too few outputs.

    22k GitHub stars~3.3k tokensUpdated today
    SecurityAuto-check passed

More from trailofbits/skills

All 79 skills in this repo
  • CodeQL Security Scan

    trailofbits/skills

    Official

    Scans a codebase for vulnerabilities with CodeQL's data flow and taint tracking in run-all or important-only modes, including data extensions for project-specific sources and sinks.

    7.4k GitHub stars~4.6k tokensUpdated 5 days ago
    Auto-check: notes
  • Code Graph Mermaid Diagrams

    trailofbits/skills

    Official

    Generates Mermaid diagrams from Trailmark code graphs, including call graphs, class hierarchies, module dependency maps, complexity heatmaps and attack surface data flows.

    7.4k GitHub stars~1.7k tokensUpdated 5 days ago
    Auto-check passed
  • Trailmark Graph Evolution

    trailofbits/skills

    Official

    Compares Trailmark code graphs at two snapshots, such as commits, tags or directories, to surface attack paths, blast radius and taint changes that text diffs miss.

    7.4k GitHub stars~3.4k tokensUpdated 5 days ago
    Auto-check passed
  • Let Fate Decide

    trailofbits/skills

    Official

    Draws a 12 Houses tarot spread to break ties when a request is vague or casually delegated, then reads the cards to pick the next step.

    7.4k GitHub stars~2.5k tokensUpdated 5 days ago
    Auto-check: notes
  • Semgrep Security Scan

    trailofbits/skills

    Official

    Detects languages, proposes rulesets for approval, then runs the approved Semgrep scan across a codebase and merges the output into one SARIF file.

    7.4k GitHub stars~3.7k tokensUpdated 5 days ago
    Auto-check: notes
  • Burp Suite Project Parser

    trailofbits/skills

    Official

    Searches and extracts data from Burp Suite project files on the command line: regex searches over responses, audit findings, proxy history and site map data.

    7.4k GitHub starsUsed in 3 repos~4.2k tokens
    Auto-check: notes

Works with

Categories

Questions about Libfuzzer

What does Libfuzzer do?

Sets up and runs libFuzzer, the coverage-guided fuzzer built into LLVM, on C/C++ code that compiles with Clang. Libfuzzer is an agent skill from trailofbits/skills, published by the product's own GitHub organization. Sets up and runs libFuzzer, the coverage-guided fuzzer built into LLVM, on C/C++ code that compiles with Clang.

When should I use Libfuzzer?

Libfuzzer fits situations like: debugging an LLVMFuzzerTestOneInput harness; starting fuzzing on a C/C++ library; choosing between libFuzzer and AFL++; working out why a libFuzzer run finds nothing.

How do I install Libfuzzer in Claude Code?

Run `npx skills add trailofbits/skills --skill libfuzzer -a claude-code`. Or copy the skill folder (plugins/testing-handbook-skills/skills/libfuzzer in trailofbits/skills) into .claude/skills/libfuzzer in your project. Claude Code loads it when a task matches its description.

How do I install Libfuzzer in Codex?

Run `npx skills add trailofbits/skills --skill libfuzzer -a codex`. Or copy the skill folder (plugins/testing-handbook-skills/skills/libfuzzer in trailofbits/skills) into .agents/skills/libfuzzer in your project. Codex loads it when a task matches its description.

Can I use Libfuzzer in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add trailofbits/skills --skill libfuzzer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/libfuzzer, .gemini/skills/libfuzzer, .github/skills/libfuzzer and .opencode/skills/libfuzzer in your project.

What does Libfuzzer need to run?

Going by SKILL.md and its folder, Libfuzzer needs the command-line tools its instructions call (curl, apt, make, cmake and brew).

Does Libfuzzer access the network?

SKILL.md names 6 domains. In commands or code: raw.githubusercontent.com and downloads.sourceforge.net; the agent is likely to contact these when it follows the instructions. As links in the text: github.com, learn.microsoft.com, llvm.org and clang.llvm.org. This is read from the text; nothing was executed.

Is Libfuzzer safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Libfuzzer use?

Libfuzzer is published under the CC-BY-SA-4.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Libfuzzer use?

About 6.1k tokens (SKILL.md is roughly 24k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Libfuzzer?

Skills that share tags, products or a category with Libfuzzer: Harness Design Fuzzing (provos/ironcurtain, 613 stars), Clusterfuzzlite (InternationalColorConsortium/iccDEV, 183 stars), Audit Native Memory Safety (cyberful/cyberful, 134 stars) and Fuzzing (mohitmishra786/low-level-dev-skills, 253 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Libfuzzer?

trailofbits (a GitHub organization, an official publisher) maintains it in trailofbits/skills, which has 7,400 GitHub stars. The repository holds 79 skills in this directory. The repository was last updated on October 2, 2026.

Source: trailofbits/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.