
WuppieFuzz is a coverage-guided REST API fuzzer from TNO built on LibAFL, designed for authorized security teams validating APIs against their OpenAPI specifications.
| Tool | TNO-S3/WuppieFuzz — coverage-guided REST API fuzzer built on LibAFL (v1.8.0, Apache-2.0, ~227 stars, Rust) |
| Category | Fuzzing / dynamic application security testing (DAST) for REST APIs |
| Primary Use | Authorized validation of REST endpoints using an OpenAPI spec, with --report endpoint and JaCoCo code coverage output |
| Safe Use | Fuzzing your own services, lab targets, or APIs under explicit written authorization during penetration tests and CI security validation — not third-party systems |
| Telemetry Note | Generates heavy, repetitive HTTP traffic against the target and writes a request database plus reports/ directories; API owners and WAFs will see obvious fuzzing patterns |
WuppieFuzz is a coverage-guided fuzzer for REST APIs developed by TNO, written in Rust and built on top of LibAFL, the modern fuzzing framework that has largely superseded the classic AFL lineage. The project's stated goals are unusually user-centric for a fuzzer: ease of use, explainability of the flaws it discovers, and modularity. It supports all three testing settings — black box, grey box and white box — meaning you can point it at a running service with nothing but an OpenAPI specification, or instrument the target for code-level feedback when you control the deployment.
The core contract is simple: you supply an OpenAPI specification (openapi.yaml or openapi.json) that describes the API's endpoints, parameters and schemas, and WuppieFuzz uses it to generate and mutate syntactically plausible requests. This spec-driven approach is what makes the tool practical for QA and DevSecOps pipelines as much as for penetration testers: the same artifact that documents the API drives the test generation, so drift between documentation and behavior becomes directly observable.
For white-box and grey-box runs, the tool integrates coverage instrumentation on the target side. The README's canonical example is a Java target with the JaCoCo agent attached: cargo run -- fuzz openapi.yaml --coverage-format jacoco --jacoco-class-dir ../Targets/app/target/classes/. The --coverage-format flag selects the feedback source, and coverage data closes the loop that makes fuzzing genuinely coverage-guided rather than blind spraying. Currently code coverage supports JaCoCo, with the team explicitly aiming to add more formats; Python coverage via LCOV is covered by the shipped example configs in example_configs/.
Configuration is layered sensibly. Every command-line argument can also be expressed in a YAML file passed via --config <CONFIG_FILE>, and where both are present, CLI arguments take precedence. The README demonstrates this with a config specifying coverage_format, output_format, source_dir, jacoco_class_dir and timeout, then overriding --timeout on the command line. For teams running repeated campaigns, this makes runs reproducible and versionable alongside the spec itself.
Reporting is where WuppieFuzz's explainability promise materializes. Running with --report creates a timestamped subdirectory under reports/ containing two kinds of coverage reports: endpoint coverage, which can always be generated because it only requires the OpenAPI spec, and code coverage, which currently requires the coverage-to-source mapping that JaCoCo provides. The harder engineering problem, as the README candidly notes, is robustly mapping coverage back to source files — a known pain point in API fuzzing generally.
Beyond static reports, the tool populates a database with all request information from the fuzzing campaign and ships a Grafana dashboard (in the dashboard/ directory) for triaging results and performance over time. This is a meaningful differentiator: instead of scrolling through thousands of raw request logs, an operator gets a queryable, visual record of what was sent, what responses came back, and how coverage evolved. For authorized engagements, that artifact trail is also useful for reporting and remediation discussions.
Installation paths are low-friction. Prebuilt binaries are published in GitHub releases for macOS, Windows and Linux, and Homebrew users can brew install wuppiefuzz directly. A Docker route exists too: docker build . -t wuppiefuzz:local, then run with -v ./fuzzing-folder:/fuzzing-folder to hold outputs, using --network host when fuzzing a service running on the host rather than in the container. The invocation wuppiefuzz:local fuzz --timeout 60 --report openapi.json captures the minimal working pattern.
Under the hood, the dependency choices reveal the architecture. WuppieFuzz vendors OpenSSL, SQLite and Z3 so a plain cargo build works out of the box. The Z3 SMT solver is the tell: it is being used for schema-aware request construction and possibly for reasoning about parameter constraints from the OpenAPI models, which is how modern API fuzzers move beyond type-blind mutation. Note that the z3 crate requires Z3 4.15+, newer than most distro packages, so Homebrew (brew install z3) is the recommended source, with LIBRARY_PATH/LD_LIBRARY_PATH adjustments on Linux.
For development builds, the repo includes cargo aliases in .cargo/config.toml — cargo dev-build, cargo dev-run, cargo dev-test — that build with --no-default-features and link against system libraries instead of the vendored copies, cutting compile times. Documentation generation is standard cargo doc --no-deps. The repository layout is well organized: coverage_agents/ holds instrumentation instructions for various target types, tutorial/ contains a deep walkthrough of fuzzing a specific target and interpreting results, and example_configs/ provides the JaCoCo and LCOV reference configurations.
The project carries credible institutional and industry validation. It has been featured at the ONE Conference, listed on openapi.tools, covered by Nordic APIs, and — notably — included in the Thoughtworks Technology Radar, which is a strong signal of real-world adoption maturity rather than an academic prototype. There is also a formal scientific publication: Rooijakkers et al., "WuppieFuzz: Coverage-Guided, Stateful REST API Fuzzing," in ICISSP 2026 proceedings, with citation details in CITATION.cff. The word "stateful" in that title indicates the fuzzer maintains request sequence awareness, not just independent per-endpoint probes.
Operationally, WuppieFuzz fits cleanly into authorized workflows: fuzz your own staging deployments in CI against the shipped OpenAPI spec, use it during scoped penetration tests where written authorization covers dynamic testing, or deploy it in a lab against deliberately vulnerable targets to study API flaw classes. The white-box mode with JaCoCo or LCOV coverage is best reserved for environments you control, since instrumentation requires target access. Because a fuzzing campaign generates substantial, patterned HTTP traffic — logged into its request database and visible to any WAF or rate limiter — pointing it at third-party infrastructure without permission would be both abusive and immediately detectable.
Licensed under Apache-2.0 with third-party notices documented in THIRD_PARTY_NOTICES, WuppieFuzz v1.8.0 is a well-maintained, thoughtfully documented option in the REST API fuzzing space alongside tools like restler and schemathesis. For teams whose APIs already publish accurate OpenAPI documents, the barrier to entry is essentially one command, and the combination of coverage feedback, timestamped reports and the Grafana triage dashboard makes the results actionable rather than just voluminous.
TNO-S3/WuppieFuzz.Educational analysis for authorized security professionals. Use only in controlled, authorized environments.
Related coverage
0 comentários:
Post a Comment
Note: Only a member of this blog may post a comment.