CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/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.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files
name:
fuzz-tool-selector
description:
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.

fuzz-tool-selector

Overview

Decision tree routing a fuzz-target authoring task to the right per-language fuzzer skill. Composes the seven per-language skills + the two references in the plugin. Picks based on target language, source-availability, and OSS-Fuzz eligibility.

When to use

  • Authoring a fuzz target - pick the right fuzzer before writing the harness.
  • Reviewing an existing fuzz target - verify the right fuzzer was selected.

Decision tree

Step 1: Identify target language(s).
        ↓
+-------+----------+--------+--------+-------+--------+--------+
| C/C++ |   Rust   |   Go   | Python |  JVM  | Other  | Binary |
|       |          |        |        |       |        | (no    |
|       |          |        |        |       |        | source)|
+-------+----------+--------+--------+-------+--------+--------+
    ↓        ↓         ↓        ↓        ↓        ↓        ↓
  Step 2:                                            AFL++
  Library    cargo-    go test  Atheris  Jazzer    Choose    -Q mode
  function?   fuzz     -fuzz                       per LLVM
   YES                                              -fsanitize
    ↓                                                support
  libFuzzer
  (in-process)
   OR
  AFL++ (file-driven)

Step 3: Is this a mature open-source project?
        ↓
        YES → also submit to OSS-Fuzz
                                            ↓
                                          ossfuzz-integration

Routing rules

Target characteristicRoute to
C / C++ library with callable function APIlibfuzzer-cpp
C / C++ binary processing filesafl-plus-plus
C / C++ source unavailableafl-plus-plus (-Q QEMU)
Rust cratecargo-fuzz-rust
Rust binary processing filesafl-plus-plus
Go packagego-native-fuzzing
Pure Python or CPython native extensionatheris-python-fuzzing
Java / Kotlin / Scala / Groovy libraryjazzer-jvm-fuzzing
Swift librarylibfuzzer-cpp (Swift wraps libFuzzer natively)
Mature open-source project (any of the above languages)Also: ossfuzz-integration (continuous 24x7 campaign)

Routing rationale

C/C++

Prefer libFuzzer for callable APIs (parsers, validators, decoders). In-process iteration is fastest. Pair with ASan + UBSan per sanitiser-integration-reference.

Switch to AFL++ when:

  • The target reads input via stdin or file argument (file-format tools, command-line utilities)
  • You need QEMU mode for closed-source binaries
  • You want a different mutation engine - AFL++ and libFuzzer find different bugs

Many mature projects run both libFuzzer and AFL++ targets in parallel.

Rust

Prefer cargo-fuzz - integrates with cargo, supports Arbitrary for structured input. Requires nightly toolchain.

For Rust binaries (not callable library APIs), AFL++ works similarly to C/C++ - wrap the binary with AFL++.

Go

Use Go native fuzzing - built into the standard testing package as of Go 1.18. Failing inputs auto-save as regression fixtures.

For binary-level Go fuzzing or fuzzing CGo dependencies, AFL++ in -Q mode works.

Python

Use Atheris - Google's libFuzzer-backed Python fuzzer. Supports both pure-Python and CPython native extensions.

For pure property-based testing in Python (without coverage guidance), consider Hypothesis in the hypothesis-testing skill (qa-property-based plugin) - complementary, not competing.

JVM

Use Jazzer - Code Intelligence's libFuzzer-backed JVM fuzzer. JUnit 5 integration via @FuzzTest. Ships JVM-level sanitisers (deserialization, SSRF, ReDoS, OS command injection).

Other languages

Languages with libFuzzer-compatible sanitiser-coverage support (Swift, Objective-C, some Haskell setups): use libFuzzer directly via the language's FFI / wrapper.

Languages without native fuzzer support (e.g., Erlang, OCaml): test via AFL++ on the compiled binary.

OSS-Fuzz overlay

Independent of the per-language choice: if the project is open-source, mature, and security-relevant, also onboard to ossfuzz-integration. OSS-Fuzz runs the existing libFuzzer / AFL++ / Jazzer harness 24x7 on Google infrastructure with automatic crash reports.

Anti-patterns

Anti-patternWhy it failsFix
Picking AFL++ for a callable C/C++ library APIOut-of-process overhead 10-100xUse libFuzzer for in-process
Picking libFuzzer for a file-processing binaryAdapter glue is complex; AFL++ handles @@ cleanlyUse AFL++
Picking cargo-fuzz on stable RustWon't compileUse nightly toolchain
Skipping OSS-Fuzz for a mature open-source projectMisses continuous 24x7 fuzzingSubmit alongside in-house CI fuzz
Mixing fuzzer outputs without considering corpus formatlibFuzzer / AFL++ corpora aren't directly compatibleUse one fuzzer's corpus; convert if needed
Routing based on language alone, ignoring "source available"Closed-source need QEMU regardless of source languageAlways factor in availability

Limitations

  • Doesn't replace per-language expertise. Knowing libFuzzer's flags vs AFL++'s requires reading the linked skill.
  • Doesn't handle cross-language targets. A JNI library: Java side via Jazzer, C side via libFuzzer; two separate campaigns.
  • OSS-Fuzz eligibility heuristic. "Mature open-source" is judgemental; OSS-Fuzz acceptance committee has the final say.

References

  • Composes per-language skills: libfuzzer-cpp, afl-plus-plus, go-native-fuzzing, cargo-fuzz-rust, atheris-python-fuzzing, jazzer-jvm-fuzzing, ossfuzz-integration.
  • Composes references: corpus-management-reference, sanitiser-integration-reference.
Workspace
testland
Visibility
Public
Created
Last updated
Publish Source
GitHub
Badge
testland/fuzz-tool-selector badge