Framework
jtpereyda/boofuzz avatar
jtpereyda/boofuzz

boofuzz: the maintained fork of the Sulley network fuzzer

A fork and successor of the Sulley Fuzzing Framework

2,362 stars382 forksPythonGPL-2.0

At a glance

What is it?
A Python network protocol fuzzer that took over when Sulley stopped being maintained, with a web UI, pluggable failure detection and eighteen worked examples in the tree.
Who is it for?
boofuzz is the practical choice if you are fuzzing a network protocol from Python and want the Sulley model without inheriting an unmaintained codebase.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why a fork of Sulley exists at all

The project's reason for existing is stated in two sentences near the top of the README: boofuzz is a fork of and successor to the Sulley fuzzing framework, and Sulley had fallen out of maintenance. That is the whole pitch, and it is a stronger one than it sounds, because Sulley was the preeminent open source network fuzzer for years and had accumulated the kind of unfixed breakage that makes a tool unusable on a modern Python.

The README lists what it kept from Sulley, and this list is worth reading as a design brief for any fuzzer: easy and quick data generation, instrumentation for failure detection, target reset after a failure, and recording of test data. Those four are the minimum viable structure of a stateful network fuzzer. You generate mutated protocol messages, you send them, you detect that the target died or misbehaved, you bring the target back, and you write down exactly what killed it.

What it changed is listed separately as features rather than fixes. Online documentation. Support for arbitrary communication mediums. Built-in support for serial fuzzing, ethernet and IP layer, and UDP broadcast. Better recording of test data. CSV export of test results. Extensible instrumentation. An easier install. And then the two words that function as a summary of the fork's motive: far fewer bugs.

The naming is a small joke that tells you the tone. Sulley was named after the fuzzy teal creature from Monsters Inc, and boofuzz is named after Boo, the one creature who scared Sulley. Licence is GPL-2.0-only per `pyproject.toml`, and the project describes itself as a Python library used to build fuzzer scripts rather than as a standalone tool.

Installation is one pip command, and the docs live on Read the Docs

The install section of the README is two lines:

bash
pip install boofuzz

That is followed by a pointer to INSTALL.rst for advanced and detailed instructions, which is where you should go if the plain install leaves you short. The README's own selling point on this front is the phrase much easier install experience, listed in capitals-free emphasis among the reasons to switch, and it is a real one: Sulley's packaging was a recurring source of friction.

The tree shows a conventional Python project rather than a package with hidden machinery. `boofuzz/` is the library, `examples/` holds eighteen scripts, `docs/` and `.readthedocs.yml` drive the documentation build, `unit_tests/` is the test suite, and `tox.ini` plus `pyproject.toml` handle multi-version testing. `CHANGELOG.rst`, `CONTRIBUTORS.txt` and `AUTHORS.txt` are all present, which is the sort of bookkeeping that separates a real project from a repository of patches.

Three scripts at the root are notable because they show how the fuzzer deals with targets it does not own. `network_monitor.py` and `process_monitor.py` observe a target's behavior during fuzzing, and `process_monitor_unix.py` is the Unix-specific variant. `vmcontrol.py` suggests the answer to targets you cannot simply restart: put them in a virtual machine and reset that instead.

A session writes results to a database and a web UI

The two features that most change how you use boofuzz are the test result recording and the web interface, and they are the same feature seen from two sides. Every test case, its inputs and its outcome go into a local database, which means a crash found at 3am is still on disk in a form you can query, and the web UI reads that database while the fuzzer runs.

The release notes make the mechanics concrete. v0.4.1 added a `Session` argument named `db_filename` to modify the location of the log database, and also fixed the check for when to enable the web app and documented the possibility of disabling it entirely. So the database is a real file you choose the location of, and the web app is a toggle rather than an unavoidable port.

v0.4.0 added runtime, execution speed and the current test case name to the web UI, plus visual request-graph rendering functions for `Session`. Rendering the request graph is the feature that deserves more attention than it gets: a network protocol is a structure of nested blocks with dependencies between them, and seeing that graph makes a malformed fuzzer script obvious in a way that reading the script does not. v0.4.2 later added the ability to bind the web UI to a specific IP address, and v0.4.0 also fixed two memory leaks in the fuzz logger, which tells you the logger is on the hot path and was worth the attention.

Combinatorial fuzzing and a generic CLI came in the same release

v0.4.0, published 2021-06-30, is the release that changed the tool's behaviour rather than adding a protocol. Three items in it matter.

The first is combinatorial fuzzing: as of this release boofuzz fuzzes multiple mutations at once by default, rather than one mutation at a time. The second is test cases specified and re-run by name, which is what makes a crash reproducible. The third is a fuzzing CLI built around `main_helper()`, which wraps your existing script in a generic command line interface instead of requiring you to write argument parsing.

That last one is an underrated design choice. A fuzzer script written as a plain Python file is easy to read and easy to version, but slow to drive: you edit constants and re-run. Wrapping the same script with `main_helper()` gives you a single binary that can point at a target, set a timeout, filter by test case name and report results, while the script itself stays declarative.

The same release also added the `Simple` primitive, which uses only the values you specify and nothing else, and a `Float` primitive with IEEE 754 encoding support. `Simple` is the one to reach for when a field has a small legal domain, like a command code or a length prefix, and letting the fuzzer mutate arbitrary bytes there mostly wastes time on rejected messages. The release notes also record that String and RandomData primitives now use a local independent instance of `random`, which is a correctness fix: sharing a global generator means two primitives fighting over the same stream and a test case that cannot be regenerated.

Eighteen examples, and the transports they cover

The `examples/` directory is the fastest way to understand the API, because each file is a complete fuzzer for one protocol and the differences between them are the actual documentation. `http_simple.py` and `http_with_body.py` are the entry points, and the difference between them is the kind of thing the API makes easy. `ftp_simple.py`, `tftp_simple.py` and `mdns.py` show stateful protocols where resetting the target matters, since FTP and TFTP both have multi-step conversations and mDNS has registration semantics.

Then there are the examples that show the extension points doing work. `fuzz_can.py` covers a CAN bus. `fuzz_ssl_client.py` and `fuzz_ssl_server.py` put fuzzing on both ends of TLS, which is a genuinely harder problem because you are fuzzing through a layer that validates structure before your target sees anything. `crc16ccitt.py` is a checksum, and `s_float.py` demonstrates the IEEE 754 primitive added in v0.4.0. `groups_demo.py` and `autoprog.py` show higher-level structure.

Two of the names are worth pausing on because they are the library aimed at a specific kind of target. `fuzz_trend_control_manager_20901.py` and `fuzz_trend_server_protect_5168.py` are numbered after the CVE identifiers of Trend Micro appliances, and `fuzz_trillian_jabber.py` covers XMPP. These are not tutorials, they are worked reproductions, and they are the best available answer to the question of what a realistic boofuzz script looks like for anything other than HTTP.

The `request_definitions/` directory at the root is related and separate from the examples. That is where reusable request fragments live, so a protocol you fuzz once can be reused as a building block in the next script rather than copied.

Version 0.4.2 dropped Python 2 and left the release history quiet

v0.4.2, published 2023-10-06, is the most recent release and it is mostly a subtraction. Six compatibility modules removed. Python 2 compatibility code removed. Object inheritance in classes removed. Minimum supported Python raised to 3.8. Poetry adopted as the build system, and `sessions.py` split into multiple files.

Alongside that it added Python 3.11 compatibility, the ability for the web UI to listen on a specific IP address, and a set of small correctness fixes that describe what accumulates in a project with many users: explicit encoding on file writes instead of the platform default, `FromFile`'s `default_value` changed from string to bytes, an out-of-date `s_update` primitive, duplicate values removed from the `BitField` primitive, and `Block`'s `dep_value` argument changed to bytes with type checking added.

The bytes-related changes are a pattern worth noticing. Several primitives gained type checking to prevent incorrect use, which is the library deciding that a silent wrong-type bug is worse than a loud error. If you are porting an older Sulley script, that is where the breakage will show up.

What has not happened since is the interesting part. Three releases are visible, the newest in October 2023, yet the repository's last push was 2026-09-21. So the code is being changed and the version number is not moving. `pyproject.toml` still carries `version = "0.4.2"` and a Development Status of 4 - Beta. Practically, treat the master branch as the current version, read CHANGELOG.rst for unreleased changes, and pin a commit rather than a release tag if you need reproducibility.

Editorial conclusion

boofuzz is the practical choice if you are fuzzing a network protocol from Python and want the Sulley model without inheriting an unmaintained codebase. The session logging, the web UI and the examples directory are the parts worth your time, and the fact that the release history stops at v0.4.2 in October 2023 while the repository was pushed to in September 2026 tells you what kind of project this is: maintained in the sense that someone is fixing it, not versioned in the sense that you get a stream of features. Read INSTALL.rst before your first run because the quickstart guides assume a working install, and start from an example in `examples/` that resembles your target rather than from the blank-slate tutorial. GPL-2.0-only means a copyleft obligation if you ship it inside a product, which is the one thing to settle before the rest.

Frequently asked questions

What is boofuzz?

boofuzz is a Python network protocol fuzzing framework forked from Sulley, which had stopped being maintained. It keeps Sulley's model of generated data, failure detection, target reset and test recording, and adds a web UI, CSV export, support for arbitrary transports and serial, ethernet, IP-layer and UDP broadcast fuzzing.

How do I install boofuzz?

Run `pip install boofuzz`. The README calls that the easy path and points at INSTALL.rst for advanced and detailed instructions. It installs as a Python library rather than a standalone binary, so what you write is a fuzzer script that imports boofuzz.

Should I use boofuzz or Sulley?

boofuzz. Sulley was the preeminent open source network fuzzer but fell out of maintenance, which is the reason the fork exists. boofuzz carries the fixes, drops Python 2, modernizes packaging with Poetry, and was pushed to in September 2026, so new protocol work should start here.

What is the web UI in boofuzz for?

It is a live view over the same log database the fuzzer writes its results into. Version 0.4.0 added runtime, execution speed and current test case name to it, along with request graph rendering, and 0.4.1 and 0.4.2 added control over where the database lives and which IP the UI binds to. The documented check for when to enable it is fixed, so it can be turned off.

Can boofuzz fuzz TLS or CAN bus traffic?

The examples directory has you covered on both. `fuzz_ssl_client.py` and `fuzz_ssl_server.py` fuzz on each side of a TLS connection, `fuzz_can.py` targets a CAN bus, and there are scripts for HTTP, FTP, TFTP, mDNS, XMPP and two numbered Trend Micro appliance CVEs. Those last two are the best models to copy for real targets.

Official sources

  1. Issues
  2. jtpereyda/boofuzz on GitHub
  3. License: GPL-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jtpereyda-boofuzz.svg)](https://hysenlabs.com/projects/jtpereyda-boofuzz)