FuzzPrep
FuzzPrep is a CLI that takes the manual effort out of building C/C++ libraries for fuzzing while aiming to minimize LLM token cost. It detects the build system, builds the library, probes harness compilation to find linker dependencies, and writes artifacts that build and link the library against a harness.
Prerequisites
What FuzzPrep needs
- Python 3.13 and
uv. git, to clone the target repository.clangandclang++, the default compilers.--ccand--cxxselect others.- libFuzzer's runtime, which
clanglinks for the default-fsanitize=fuzzerharness flags. It is a separate package:libclang-rt-devon Debian and Ubuntu,compiler-rtelsewhere. A plainapt install clangpulls it in as a recommended package, but an install that uses--no-install-recommendsdoes not, so name it.
sudo apt update
sudo apt install -y git clang libclang-rt-dev
Common library build dependencies
A target brings its own build dependencies: the build system it uses, and the -dev packages
it links against. FuzzPrep reports the packages a failed run is missing. The below script also installs a set that covers many targets — the four supported build systems, the usual codegen and
archive utilities, and the libraries FuzzPrep knows how to identify from error traces:
./scripts/install_common_deps.sh
The list is not exhaustive. When a build fails on a dependency the script does not cover, install that dependency and run again.
Optional
- Docker, for
--environment oss-fuzz. - The
claudeorcodexCLI, for agent repair. It is on by default;--no-agentsturns it off and no CLI is then needed. bear, for Make and Autotools targets built with--environment local. It capturescompile_commands.json, whichextract-featuresandgenerate-yamlread.cmake,llvm-dev,libclang-20, andlibclang-dev, whichextract-featuresbuilds its Clang LibTooling parser against. With more than one LLVM installed, pointCMAKE_PREFIX_PATHat the tree theclangonPATHbelongs to.
The apt packages among these:
sudo apt install -y bear cmake llvm-dev libclang-dev libclang-20
Install
uv sync
Quickstart
Best practice: Run FuzzPrep in a container or disposable VM. FuzzPrep compiles and executes arbitrary build-system logic from the target library. Its agentic workflow may also write and execute build scripts, so it should be run in an isolated environment.
From a local checkout after uv sync:
# Clones the repository, builds it, verifies it, and writes `output/zlib/`.
uv run fuzzprep generate https://github.com/madler/zlib.git
To run FuzzPrep without cloning this repository:
uvx fuzzprep generate https://github.com/madler/zlib.git
Other useful flags include:
# Verify in the OSS-Fuzz Docker environment instead of on the host
uv run fuzzprep generate <REPO_URL> --environment oss-fuzz
# Turn off agent repair: a failed build then simply fails the run
uv run fuzzprep generate <REPO_URL> --no-agents
# Pass build-system configure options (repeat for more than one)
uv run fuzzprep generate <REPO_URL> --library-configure-arg=-DCARES_STATIC=ON
# Skip the from-scratch rebuild that validates an agent's repair, for a faster run
uv run fuzzprep generate <REPO_URL> --bypass-scratch-validation
# Use distinct library and final-harness instrumentation defaults
uv run fuzzprep generate <REPO_URL> --environment local \
--cc clang --cxx clang++ \
--library-cflags='-fsanitize=fuzzer-no-link,address' \
--library-cxxflags='-fsanitize=fuzzer-no-link,address' \
--harness-cflags='-fsanitize=fuzzer,address' \
--harness-cxxflags='-fsanitize=fuzzer,address'
Agent repair is on by default and calls a paid network service. --agent claude (the
default) or --agent codex selects the backend; --no-agents turns it off.
See uv run fuzzprep generate --help for the full set of options (custom output
location, pinning a branch/tag/commit, a different base image, etc).
Adaptable builds
The generated build scripts let you supply your own toolchain and flags:
CC=afl-clang-fast CXX=afl-clang-fast++ \
CFLAGS=-fsanitize=address CXXFLAGS=-fsanitize=address \
./build_library.sh
When a run fails
FuzzPrep keeps its working state in .fuzzprep/<project>/: the workspace it built in,
logs/ with the raw output of each phase, and stats.json. A failed run writes no output
directory, but the library build artifacts stay in .fuzzprep/<project>/install/ if you want
to debug the link line there. Add --log-level debug for more detail, or --quiet to hide
the raw subprocess output while a phase runs.
What it does
- Detects the build system: CMake, Meson, Autotools, or Makefile.
- Builds the library with a deterministic script. If that build fails, an agent repairs it.
- Probes harness compilation to find transitive linker dependencies. If the probe fails, an agent repairs it.
- Writes the output directory
<output>/<project>/.
Output
The output directory provides a reproducible OSS-Fuzz project and a standalone host build
tree. docker build . works, and so does ./setup.sh && ./build_library.sh.
output/<project>/
├── Dockerfile # OSS-Fuzz project files
├── project.yaml # OSS-Fuzz project metadata
├── .dockerignore
├── setup.sh # Script for repo clone + apt dependencies
├── build.sh # Builds the library and compiles the provided harness
├── build_library.sh # build and install the library into install/
├── compile_harness.sh # compile and link one harness source
├── compile_harnesses.sh # compile every source in harness_source/ into out/
├── harness_source/ # source code of all harnesses
├── install/ # the library this run built
├── compile_commands.json # captured compile commands
├── stats.json # what this run did: durations, agent use, status
└── README.md # what this run verified, and how to run it
harness_source/ starts with a stub — an LLVMFuzzerTestOneInput with a
// TODO: Add fuzzing logic body. FuzzPrep proves the harness compiles and links against
the library; writing the fuzzing logic is yours.
Environments
--environment selects where this run builds and verifies. It does not change what is
generated: the output directory always holds both setups. The generated README.md records
which of the two this run exercised.
local— build and verify on the host.oss-fuzz— build and verify in an OSS-Fuzz compatible Docker container, then prove the generated Dockerfile builds from scratch.
Neither environment isolates the target's build from your machine well enough to trust it. Run both inside a VM or an isolated machine.
Other commands
generate produces a compile_commands.json file that two follow-on commands consume, to
extract the library's API surface (extract-features) and to produce an OSS-Fuzz-Gen
compatible YAML input (generate-yaml).
uv run fuzzprep extract-features <BUILD_PATH> # -> features.json (run this first)
uv run fuzzprep generate-yaml <BUILD_PATH> # -> <project>.yaml
extract-features runs a Clang LibTooling-based parser over every header and source file in
compile_commands.json. It writes <BUILD_PATH>/features.json, a structured inventory of
the library's C/C++ declarations:
functions— name, return type, parameters, full signature, declaring header, and whether it is public API (declared in a header, notstatic)typedefs— name, underlying type, declaring headermacros— name, object- or function-like, parameters (if function-like), value, declaring headerenums— name (if any), enumerators with their values, declaring headerrecords— structs and unions: name (if any),kind, fields, declaring headerwarnings— non-fatal problems found during the parse
generate-yaml reads features.json and keeps only the public functions. To get
finer-grained output, name one or more headers and it keeps only the functions those headers
declare:
uv run fuzzprep generate-yaml <BUILD_PATH> zlib.h zconf.h
Run uv run fuzzprep --help for details.
Security
FuzzPrep clones and builds arbitrary third-party repositories, which runs their build systems on your machine, and it hands a repair agent write access to the run's workspace.
Run it in a VM or on a dedicated machine you can wipe, whatever --environment you pick. A
container shares the host kernel and is not a boundary that holds against code written to
break out of one, so --environment oss-fuzz reduces the blast radius of an ordinary build
but does not contain a hostile one. --no-agents turns agent repair off.
SECURITY.md has the full threat model and tells you how to report a vulnerability.
Contributing
See CONTRIBUTING.md for the local setup, the checks a pull request must pass, and what each pytest marker needs. Participation is governed by the Code of Conduct.
License
FuzzPrep is licensed under Apache-2.0.
The feature_extractor tool that extract-features builds links cJSON and the LLVM/Clang
libraries. THIRD_PARTY_NOTICES.md records their licenses and the
notices that apply if you redistribute that binary.
Some files under tests/real_harnesses/ come from upstream projects and keep their own
licenses; that directory's README records the provenance of
each one.
Metadata
Release files for fuzzprep 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fuzzprep-0.1.0.tar.gz | 91.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fuzzprep-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 212.5 kB
Release files / fuzzprep-0.1.0.tar.gz
| Download URL | fuzzprep-0.1.0.tar.gz |
|---|---|
| Size | 91.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
857fe41a13deddfecf3a33a5be81e8b380c574166c179c3bd3cf03d4262d5df5
|
|
BLAKE2b-256 checksum How to use checksums |
f3e463a2e3db0ede8f0694c0f1d14c733ff6efa93902523eb86187ccc7970dd9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fuzzprep-0.1.0-py3-none-any.whl
| Download URL | fuzzprep-0.1.0-py3-none-any.whl |
|---|---|
| Size | 120.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f93e7841a1f3d8bad5f906b514aa6694b9ad7601eb833b164a8951e027c7095c
|
|
BLAKE2b-256 checksum How to use checksums |
8acd157676fc966a07195ad2fb4222baff2a131c8e92db1147551c725a76c859
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log