ossfuzz-integration
Author and submit a project to Google OSS-Fuzz - the open-source continuous fuzzing service that runs libFuzzer / AFL++ / Honggfuzz campaigns on Google infrastructure 24x7. Covers the project.yaml + Dockerfile + build.sh contract, the $OUT/$WORK conventions, supported languages + sanitisers, seed-corpus + dictionary submission, the OSS-Fuzz Build Status dashboard, and the disclosure SLA (issues filed in Monorail with 90-day deadline). Use to offload long-running fuzz campaigns to dedicated infrastructure rather than self-hosting.
Install with skills.sh (any agent)
npx skills add testland/qa --skill ossfuzz-integrationossfuzz-integration
Overview
OSS-Fuzz (per google.github.io/oss-fuzz (opens in new window)) runs libFuzzer / AFL++ / Honggfuzz campaigns 24x7 on Google Cloud across multiple sanitiser configurations (ASan, UBSan, MSan), auto-files bug reports with crash reproducers, and tracks fix status with a 90-day disclosure SLA.
For corpus discipline see corpus-management-reference; for sanitiser pairing see sanitiser-integration-reference.
When to use
For commercial / closed-source projects: ClusterFuzz (the open-source backend behind OSS-Fuzz) can be self-hosted.
How to use
Authoring
Each project lives at projects/<project-name>/ with three files: project.yaml (metadata - language, fuzzing_engines, sanitizers, contacts), a Dockerfile that builds the fuzz targets on base-builder, and a build.sh that produces $OUT/<fuzz_target> plus seed corpora. Verify locally with infra/helper.py before opening the PR.
Full field-by-field contract, file templates, and the local-testing commands: references/project-contract.md.
Running
Submitting a new project
Receiving findings
Bugs are filed in Monorail (issues.oss-fuzz.com) with:
After the 90-day deadline, unfixed bugs become public.
Updating an existing project
Fork -> modify -> PR. Common changes:
Parsing results
OSS-Fuzz crash artefact format matches libFuzzer's. The Monorail issue includes:
Feed this to bug-report-from-failure for downstream bug-tracker filing.
Worked example
A maintainer wants continuous fuzzing for a JPEG decoder library. They add projects/jpeg-decoder/ with language: c, fuzzing_engines: [libfuzzer, afl], sanitizers: [address, undefined], and primary_contact set. build.sh compiles the decoder and links decompress_fuzzer against $LIB_FUZZING_ENGINE, then copies decompress_fuzzer_seed_corpus.zip (sample JPEGs) to $OUT. Locally, python infra/helper.py check_build jpeg-decoder passes. They open the PR; OSS-Fuzz merges it about a week later. A few days in, Monorail files a heap-buffer-overflow in the Huffman decoder with an attached reproducer. They run python infra/helper.py reproduce jpeg-decoder decompress_fuzzer crash-abc123, confirm the bug, patch it, and the issue closes before the 90-day deadline.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Submitting an experimental harness | Slow path discovery wastes OSS-Fuzz compute | Mature harness locally first; ≥10k execs/sec |
| No seed corpus | Wastes first weeks rediscovering shallow inputs | Submit <target>_seed_corpus.zip with the project |
| No dictionary for structured formats | Slow grammar discovery | Submit <target>.dict |
| Fuzz target builds incompletely with MSan | Build matrix slot wasted | Skip MSan in project.yaml until dependencies instrumented |
Stale main_repo URL | OSS-Fuzz pulls from wrong branch | Keep main_repo current |
| Missing primary_contact / auto_ccs | Bug reports go nowhere | Always set contact emails |
| Fix-then-ignore | Disclosure deadline still applies; the bug becomes public 90 days later | Fix within deadline OR request extension |
Limitations
References
OSS-Fuzz project contract
View source (opens in new window)OSS-Fuzz project contract
The projects/<project-name>/ file contract - project.yaml, Dockerfile, build.sh - plus how to verify it locally before submitting.
Project layout in OSS-Fuzz repo
Per the OSS-Fuzz docs at google.github.io/oss-fuzz/getting-started/new-project-guide (opens in new window), each project lives at projects/<project-name>/ and contains:
projects/<project-name>/
project.yaml # metadata: language, fuzzing_engines, sanitizers, primary_contact
Dockerfile # builds the fuzz targets
build.sh # produces $OUT/<fuzz_target_1> + seed corpora
project.yaml
homepage: "https://example.com/project"
language: c++ # or c, rust, go, python, jvm, swift
fuzzing_engines:
- libfuzzer
- afl
- honggfuzz
sanitizers:
- address
- undefined
- memory
primary_contact: "maintainer@example.com"
auto_ccs:
- "security@example.com"
main_repo: "https://github.com/example/project"
Per the OSS-Fuzz docs, language drives which build template is used; fuzzing_engines × sanitizers enumerates the build matrix (libFuzzer + ASan, libFuzzer + UBSan, libFuzzer + MSan, AFL + ASan, etc.).
Dockerfile
FROM gcr.io/oss-fuzz-base/base-builder
# Install dependencies
RUN apt-get update && apt-get install -y \
cmake ninja-build
# Clone the source
RUN git clone --depth=1 https://github.com/example/project /src/project
WORKDIR /src/project
# Copy build script + seed corpus
COPY build.sh fuzz_target_1.cc fuzz_target_1_seed_corpus.zip $SRC/
WORKDIR /src/project
Per OSS-Fuzz docs, the base image (base-builder) provides clang + libFuzzer + afl-clang-fast + sanitisers preinstalled. Language-specific base images exist (base-builder-rust, base-builder-go, base-builder-jvm, etc.).
build.sh
#!/bin/bash -eu
# OSS-Fuzz sets $OUT, $WORK, $CC, $CXX, $CFLAGS, $CXXFLAGS, $LIB_FUZZING_ENGINE
# Build the library
cd /src/project
mkdir -p build && cd build
cmake -G Ninja .. \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF
ninja
# Build fuzz target
$CXX $CXXFLAGS \
-I/src/project/include \
/src/fuzz_target_1.cc \
/src/project/build/libproject.a \
$LIB_FUZZING_ENGINE \
-o $OUT/fuzz_target_1
# Seed corpus
cp /src/fuzz_target_1_seed_corpus.zip $OUT/fuzz_target_1_seed_corpus.zip
# Dictionary (optional)
cp /src/fuzz_target_1.dict $OUT/fuzz_target_1.dict
Per OSS-Fuzz docs:
Local testing
Before submitting, verify locally with the helper script:
git clone https://github.com/google/oss-fuzz
cd oss-fuzz
python infra/helper.py build_image <project-name>
python infra/helper.py build_fuzzers --sanitizer address <project-name>
python infra/helper.py check_build <project-name>
python infra/helper.py run_fuzzer <project-name> fuzz_target_1
Per the OSS-Fuzz docs, check_build validates the harness will run on Google infrastructure.
Related skills
afl-plus-plus
Author and run AFL++ - out-of-process coverage-guided fuzzer (a community fork of Google's original AFL with improved mutations and instrumentation). Covers afl-cc / afl-clang-fast instrumented build, afl-fuzz invocation, parallel master/slave (-M / -S), dictionary support (-x), QEMU mode (-Q) for binaries without source, output structure (queue / crashes / hangs), crash minimisation (afl-tmin), corpus minimisation (afl-cmin), crash filename triage, and CI integration. Use for fuzzing standalone binaries (file processors, command-line tools) where libFuzzer's in-process model doesn't fit; for cross-fuzzer corpus strategy see corpus-management-reference.
atheris-python-fuzzing
Author and run Atheris - Google's Python coverage-guided fuzzer built on libFuzzer. Covers pip installation, atheris.Setup + atheris.Fuzz invocation, TestOneInput(data: bytes) target signature, FuzzedDataProvider for structured input, instrument_imports() / instrument_func decorators for coverage instrumentation, and libFuzzer-passthrough flags (-atheris_runs, -max_total_time, -dict). Use for fuzzing Python libraries - also supports CPython native-extension fuzzing.
cargo-fuzz-rust
Author and run cargo-fuzz - Rust fuzzing via libFuzzer with cargo integration. Covers `cargo install cargo-fuzz`, `cargo fuzz init` + `cargo fuzz add {target}` for harness scaffolding, the `fuzz_target!` macro for entry-point declaration, the `Arbitrary` trait for structured input mutation, and `cargo fuzz run` invocation. Requires Rust nightly. Use for fuzz testing Rust libraries - cargo-fuzz wraps libFuzzer with native Rust ergonomics.
corpus-management-reference
Pure-reference catalog of fuzz-corpus management practices. Defines what a corpus is (seed corpus + evolved corpus saved by the fuzzer), corpus directory layout per libFuzzer / AFL++ / Go native / cargo-fuzz / OSS-Fuzz, the canonical crash-artefact naming (crash-{sha1} / leak-{sha1} / timeout-{sha1}), seed corpus construction strategies (sample-from-prod, sample-from-test-fixtures, from-spec-keywords), corpus minimisation, dictionary files, and the OSS-Fuzz integration corpus sync. Use as the corpus-discipline reference when building a fuzz target or maintaining a long-running fuzz campaign.
crash-triage-reference
Pure-reference catalog for manually triaging individual fuzzer crash artifacts - reading ASan, UBSan, and MSan output; classifying findings as LIKELY-EXPLOITABLE, MEDIUM, or BENIGN; deduplicating by stack-hash; and minimizing reproducers with -minimize_crash. Use when you need to understand what a specific crash means, build exploitability intuition, or manually work a small set of findings. For automated bulk triage across a full artifact directory, run automated findings triage instead.
fuzz-tool-selector
Routes a fuzz-target authoring task to the right fuzzer for the detected language and build type. Decision tree: C/C++ → libfuzzer-cpp + afl-plus-plus; Rust → cargo-fuzz-rust (or libfuzzer-cpp via FFI); Go → go-native-fuzzing; Python → atheris-python-fuzzing; JVM → jazzer-jvm-fuzzing; closed-source binary → afl-plus-plus in QEMU mode; mature open-source project → ossfuzz-integration. Use when a project needs coverage-guided fuzzing and no fuzzer has been chosen for its language or toolchain yet.
go-native-fuzzing
Author and run Go's native fuzzing (Go 1.18+) - coverage-guided fuzzing built into the standard testing package via FuzzXxx functions. Covers f.Add seed-corpus declaration, f.Fuzz callback signature with typed parameters, testdata/fuzz/{FuzzXxx}/ directory layout for seeds + regression cases, the -fuzz flag for `go test`, and CI integration via short smoke runs. Use for fuzz testing Go libraries - Go's native approach integrates seamlessly with standard `go test` rather than requiring a separate toolchain like AFL++.
jazzer-jvm-fuzzing
Author and run Jazzer - Code Intelligence's JVM coverage-guided fuzzer built on libFuzzer. Covers Maven / Gradle / standalone JAR installation, the @FuzzTest annotation (JUnit 5 integration), typed parameter mutation (String, primitives, byte[]), built-in JVM sanitisers (SSRF / path traversal / OS command injection / deserialization gadget / ReDoS), and the JAZZER_FUZZ=1 env var to switch between regression and fuzzing modes. Use for fuzz testing Java / Kotlin libraries - particularly effective against parsing, deserialization, and HTTP-handling code.
libfuzzer-cpp
Author and run LLVM libFuzzer for C/C++ - in-process coverage-guided fuzzing. Covers harness authoring (LLVMFuzzerTestOneInput entry point), build with -fsanitize=fuzzer,address,undefined, runtime flags (-max_total_time, -runs, -dict, -fork, -workers), corpus + crash-artefact handling, and CI integration. Use for libraries / parsers / decoders in C/C++ where in-process fuzzing of a function is the right scope. Compose with ASan + UBSan from sanitiser-integration-reference and corpus discipline from corpus-management-reference.
sanitiser-integration-reference
Pure-reference catalog of compiler sanitisers used with fuzz testing - AddressSanitizer (ASan), UndefinedBehaviorSanitizer (UBSan), MemorySanitizer (MSan), ThreadSanitizer (TSan), and LeakSanitizer (LSan). Explains what each detects, compatibility (can ASan + UBSan combine? - yes; ASan + MSan? - no), build flags, runtime options (ASAN_OPTIONS / UBSAN_OPTIONS env vars), and the typical ~2x slowdown per ASan. Use to pick the right sanitiser per fuzz target, configure the build, and interpret crash reports.