Code Audit
3stoneBrother/code-audit
Professional code security audit skill covering 55+ vulnerability types.
Sets up and runs AFL++ for multi-core fuzzing of C/C++ projects built with afl-clang-fast or afl-gcc-fast.
$ npx skills add trailofbits/skills --skill aflpp -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install trailofbits/skills aflpp --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/testing-handbook-skills/skills/aflpp .claude/skills/aflpp && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "aflpp" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills/skills/aflpp into .claude/skills/aflpp/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "aflpp", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills/skills/aflppType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add trailofbits/skills --skill aflpp -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install trailofbits/skills aflpp --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/testing-handbook-skills/skills/aflpp .agents/skills/aflpp && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "aflpp" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills/skills/aflpp into .agents/skills/aflpp/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "aflpp", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add trailofbits/skills --skill aflpp -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install trailofbits/skills aflpp --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/testing-handbook-skills/skills/aflpp .cursor/skills/aflpp && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "aflpp" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills/skills/aflpp into .cursor/skills/aflpp/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "aflpp", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/trailofbits/skills.git --path plugins/testing-handbook-skills/skills/aflpp--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add trailofbits/skills --skill aflpp -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install trailofbits/skills aflpp --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/testing-handbook-skills/skills/aflpp .gemini/skills/aflpp && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "aflpp" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills/skills/aflpp into .gemini/skills/aflpp/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "aflpp", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install trailofbits/skills aflppInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add trailofbits/skills --skill aflpp -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/testing-handbook-skills/skills/aflpp .github/skills/aflpp && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "aflpp" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills/skills/aflpp into .github/skills/aflpp/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "aflpp", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add trailofbits/skills --skill aflpp -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install trailofbits/skills aflpp --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/testing-handbook-skills/skills/aflpp .opencode/skills/aflpp && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "aflpp" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills/skills/aflpp into .opencode/skills/aflpp/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "aflpp", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
aflppSets up and runs AFL++ for multi-core fuzzing of C/C++ projects built with afl-clang-fast or afl-gcc-fast.
Aflpp is an agent skill from trailofbits/skills, published by the product's own GitHub organization. Sets up and runs AFL++ for multi-core fuzzing of C/C++ projects built with afl-clang-fast or afl-gcc-fast. Covers instrumentation modes, parallel main and secondary campaigns, persistent mode, corpus minimization, and crash triage. Use when scaling fuzzing across cores, fuzzing a mature C/C++ codebase, reading the afl-fuzz status screen, or moving on after libFuzzer has plateaued.
Its SKILL.md is about 5.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 4 other files, including assets (for example `agents/openai.yaml`).
It sits in Security, covering Fuzzing. It works with C++ and Docker. The repository describes itself as: Trail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows. The licence is CC-BY-SA-4.0.
2 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 82fe822. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
dockerbashaptgitcurlFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
github.comraw.githubusercontent.comAlso links to:
youtube.comaflplus.plusblog.ritsec.clubusenix.orgblog.trailofbits.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Aflpp loads about 5.6k tokens when it runs. Until then it costs about 97 tokens; SKILL.md has 2,025 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from trailofbits/skills at commit 82fe822, republished under its CC-BY-SA-4.0 licence (© trailofbits). 2,025 words, ~5,595 tokens.
.claude/skills/aflpp/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.AFL++ is a fork of the original AFL fuzzer that offers better fuzzing performance and more advanced features while maintaining stability. A major benefit over libFuzzer is that AFL++ has stable support for running fuzzing campaigns on multiple cores, making it ideal for large-scale fuzzing efforts.
| Fuzzer | Best For | Complexity |
|---|---|---|
| AFL++ | Multi-core fuzzing, diverse mutations, mature projects | Medium |
| libFuzzer | Quick setup, single-threaded, simple harnesses | Low |
| LibAFL | Custom fuzzers, research, advanced use cases | High |
Choose AFL++ when:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Call your code with fuzzer-provided data
check_buf((char*)data, size);
return 0;
}Compile and run:
# Setup AFL++ wrapper script first (see Installation)
./afl++ docker afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
mkdir seeds && echo "aaaa" > seeds/minimal_seed
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzzAFL++ has many dependencies including LLVM, Python, and Rust. We recommend using a current Debian or Ubuntu distribution for fuzzing with AFL++.
| Method | When to Use | Supported Compilers |
|---|---|---|
| Ubuntu/Debian repos | Recent Ubuntu, basic features only | Ubuntu 23.10: Clang 14 & GCC 13<br>Debian 12: Clang 14 & GCC 12 |
| Docker (from Docker Hub) | Specific AFL++ version, Apple Silicon support | As of 4.35c: Clang 19 & GCC 11 |
| Docker (from source) | Test unreleased features, apply patches | Configurable in Dockerfile |
| From source | Avoid Docker, need specific patches | Adjustable via LLVM_CONFIG env var |
Prior to installing afl++, check the clang version dependency of the packge with apt-cache show afl++, and install the matching lld version (e.g., lld-17).
apt install afl++ lld-17docker pull aflplusplus/aflplusplus:stablegit clone --depth 1 --branch stable https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
docker build -t aflplusplus .Refer to the Dockerfile for Ubuntu version requirements and dependencies. Set LLVM_CONFIG to specify Clang version (e.g., llvm-config-18).
Create a wrapper script to run AFL++ on host or Docker:
cat <<'EOF' > ./afl++
#!/bin/sh
AFL_VERSION="${AFL_VERSION:-"stable"}"
case "$1" in
host)
shift
bash -c "$*"
;;
docker)
shift
/usr/bin/env docker run -i \
--privileged \
-v ./:/src \
--rm \
--name "afl_fuzzing_$$" \
"aflplusplus/aflplusplus:$AFL_VERSION" \
bash -c "cd /src && bash -c \"$*\""
;;
*)
echo "Usage: $0 {host|docker}"
exit 1
;;
esac
EOF
chmod +x ./afl++The examples below use docker mode, apart from the system configuration commands that have to reach the host kernel. Swap in host to run any of them against an AFL++ installed on the machine itself. The wrapper joins everything after the mode argument into a single shell string, so quoting does not survive: an argument containing a space (-x "my dict.dict") arrives word-split. Rename such files without spaces, or edit the wrapper for that run.
The missing -t is deliberate. docker run -ti aborts with the input device is not a TTY whenever stdin is not a terminal, which covers CI jobs and anything an agent or script drives. afl-fuzz notices there is no terminal and prints plain status lines in place of the full-screen UI. A program that insists on a terminal, such as watch, has to run on the host side of the wrapper instead. $$ expands to the wrapper's PID, so parallel instances get distinct container names rather than colliding on a single afl_fuzzing. docker ps truncates the COMMAND column, so every row looks alike; use docker ps --no-trunc to tell the instances apart before stopping one.
Security Warning: The afl-system-config and afl-persistent-config scripts require root privileges and disable OS security features. Do not fuzz on production systems or your development environment. Use a dedicated VM instead.
Run after each reboot for up to 15% more executions per second:
./afl++ host afl-system-configafl-system-config tunes the kernel it runs against, so run it on the machine that hosts the campaign. ./afl++ docker afl-system-config reaches the same settings through the wrapper's --privileged container, which is the only route when AFL++ is installed via Docker alone.
For maximum performance, disable kernel security mitigations (requires grub bootloader, not supported in Docker):
./afl++ host afl-persistent-config
update-grub
reboot
./afl++ host afl-system-configVerify with cat /proc/cmdline - output should include mitigations=off.
AFL++ supports libFuzzer-style harnesses:
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 1. Validate input size if needed
if (size < MIN_SIZE || size > MAX_SIZE) return 0;
// 2. Call target function with fuzz data
target_function(data, size);
// 3. Return 0 (non-zero reserved for future use)
return 0;
}| Do | Don't |
|---|---|
| Reset global state between runs | Rely on state from previous runs |
| Handle edge cases gracefully | Exit on invalid input |
| Keep harness deterministic | Use random number generators |
| Free allocated memory | Create memory leaks |
| Validate input sizes | Process unbounded input |
See Also: For detailed harness writing techniques, patterns for handling complex inputs, and advanced strategies, see the fuzz-harness-writing technique skill.
AFL++ offers multiple compilation modes with different trade-offs.
Choose your compilation mode:
afl-clang-lto): Best performance and instrumentation. Try this first.afl-clang-fast): Fall back if LTO fails to compile.afl-gcc-fast): For projects requiring GCC../afl++ docker afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz./afl++ docker afl-g++-fast -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzImportant: GCC version must match the version used to compile the AFL++ GCC plugin.
./afl++ docker AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzSee Also: For detailed sanitizer configuration, common issues, and advanced flags, see the address-sanitizer and undefined-behavior-sanitizer technique skills.
Note that -g is not necessary, it is added by default by the AFL++ compilers.
| Flag | Purpose |
|---|---|
-DNO_MAIN=1 | Skip main function when using libFuzzer harness |
-O2 | Production optimization level (recommended for fuzzing) |
-fsanitize=fuzzer | Enable libFuzzer compatibility mode and adds the fuzzer runtime when linking executable |
-fsanitize=fuzzer-no-link | Instrument without linking fuzzer runtime (for static libraries and object files) |
AFL++ requires at least one non-empty seed file:
mkdir seeds
echo "aaaa" > seeds/minimal_seedFor real projects, gather representative inputs:
After a campaign, minimize the corpus to keep only unique coverage:
./afl++ docker afl-cmin -i out/default/queue -o minimized_corpus -- ./fuzzSee Also: For corpus creation strategies, dictionaries, and seed selection, see the fuzzing-corpus technique skill.
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzz./afl++ docker AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzzAFL++ reports these statistics either way, but how you read them depends on the
mode. The wrapper's docker run -i gives the container no TTY, so afl-fuzz
drops the full-screen UI and writes plain status lines to the log instead — the
fields below appear there, and in state/<instance>/fuzzer_stats. To get the
interactive UI, run host mode in a terminal, or add -t to the wrapper for a
run you are watching by hand.
| Output | Meaning |
|---|---|
| execs/sec | Execution speed - higher is better |
| cycles done | Number of queue passes completed |
| corpus count | Number of unique test cases in queue |
| saved crashes | Number of unique crashes found |
| stability | % of stable edges (should be near 100%) |
out/default/
├── cmdline # How was the SUT invoked?
├── crashes/ # Inputs that crash the SUT
│ └── id:000000,sig:06,src:000002,time:286,execs:13105,op:havoc,rep:4
├── hangs/ # Inputs that hang the SUT
├── queue/ # Test cases reproducing final fuzzer state
│ ├── id:000000,time:0,execs:0,orig:minimal_seed
│ └── id:000001,src:000000,time:0,execs:8,op:havoc,rep:6,+cov
├── fuzzer_stats # Campaign statistics
└── plot_data # Data for plottingView live campaign statistics:
./afl++ docker afl-whatsup outCreate coverage plots. The aflplusplus image already ships gnuplot-nox; in host mode, install gnuplot first with apt install gnuplot.
./afl++ docker afl-plot out/default out_graph/Pass one of the filenames from out/default/crashes/:
./afl++ docker ./fuzz out/default/crashes/id:000000,sig:06,src:000002,time:286,execs:13105,op:havoc,rep:4| Option | Purpose |
|---|---|
-G 4000 | Maximum test input length (default: 1048576 bytes) |
-t 1000 | Timeout in milliseconds for each test case (default: 1000ms) |
-m 1000 | Memory limit in megabytes (default: 0 = unlimited) |
-x ./dict.dict | Use dictionary file to guide mutations |
AFL++ has many environment variables, but most are niche. These are the ones that matter in practice.
# Every campaign should use tmpfs — SSDs will thank you, and it's faster
AFL_TMPDIR=/dev/shmAFL_TMPDIR is a free performance win with no downsides — not setting it wears out your SSD and slows fuzzing.
# Speeds up calibration ~2.5x — use when targets are slow (e.g., >10 ms/exec)
AFL_FAST_CAL=1AFL_FAST_CAL reduces calibration time with negligible precision loss. Recommended specifically for slow targets where calibration would otherwise take a long time.
# On the primary (-M) instance only — needed for afl-cmin, not for fuzzing itself
AFL_FINAL_SYNC=1
# On all instances — cache test cases in memory (default: 50 MB, good range: 50-250 MB)
AFL_TESTCACHE_SIZE=100AFL_FINAL_SYNC tells the primary instance to do a final import from all secondaries when stopping. This does not affect the fuzzing process itself — it only matters when you later run afl-cmin for corpus minimization, ensuring the primary's queue has the full combined corpus. AFL_TESTCACHE_SIZE caches test cases in memory to reduce disk I/O; the default is 50 MB and values between 50-250 MB work well for most campaigns.
# Fail fast if fuzzing isn't finding anything
AFL_EXIT_ON_TIME=3600 # 1 hour with no new paths = stop
# Or run until "done" (all queue entries processed)
AFL_EXIT_WHEN_DONE=1
# Headless environments
AFL_NO_UI=1Unbounded fuzzing in CI wastes resources. Set time limits or use exit conditions.
| Variable | Why Skip It |
|---|---|
AFL_NO_ARITH | Can hurt coverage on binary formats, but may be useful for text-based targets |
AFL_SHUFFLE_QUEUE | Only for exotic setups, usually harmful |
AFL_DISABLE_TRIM | Trimming is valuable, don't disable without reason |
AFL++ excels at multi-core fuzzing with two major advantages:
Start the primary fuzzer (in background):
./afl++ docker afl-fuzz -M primary -i seeds -o state -- ./fuzz 1>primary.log 2>primary.error </dev/null &Start secondary fuzzers (as many as you have cores):
./afl++ docker afl-fuzz -S secondary01 -i seeds -o state -- ./fuzz 1>secondary01.log 2>secondary01.error </dev/null &
./afl++ docker afl-fuzz -S secondary02 -i seeds -o state -- ./fuzz 1>secondary02.log 2>secondary02.error </dev/null &The </dev/null is required, not decorative. docker run -i keeps the client
reading its own stdin, and a backgrounded process that reads the terminal is sent
SIGTTIN, whose default action stops it — so without the redirect these jobs show
up as Stopped in jobs and never fuzz.
List all running jobs:
jobsView live statistics. watch needs a terminal that docker run -i does not give it, so wrap the whole invocation instead of running watch inside the container. Every tick starts a container, which is why the interval is 5 seconds rather than 1:
watch -n5 --color ./afl++ docker afl-whatsup state/kill $(jobs -p)AFL++ automatically tracks coverage through edge instrumentation. Coverage information is stored in fuzzer_stats and plot_data.
Use afl-plot to visualize coverage over time:
./afl++ docker afl-plot out/default out_graph/See Also: For detailed coverage analysis techniques, identifying coverage gaps, and systematic coverage improvement, see the coverage-analysis technique skill.
CMPLOG/RedQueen is the best path constraint solving mechanism available in any fuzzer. To enable it, the fuzz target needs to be instrumented for it. Before building the fuzzing target set the environment variable:
./afl++ docker AFL_LLVM_CMPLOG=1 makeNo special action is needed for compiling and linking the harness.
To run a fuzzer instance with a CMPLOG instrumented fuzzing target, add -c0 to the command like arguments:
./afl++ docker afl-fuzz -c0 -S cmplog -i seeds -o state -- ./fuzz 1>cmplog.log 2>cmplog.error </dev/null &Sanitizers are essential for finding memory corruption bugs that don't cause immediate crashes.
./afl++ docker AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzzNote: Memory limit (-m) is not supported with ASan due to 20TB virtual memory reservation.
./afl++ docker AFL_USE_UBSAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer,undefined harness.cc main.cc -o fuzz| Issue | Solution |
|---|---|
| ASan slows fuzzing | Use only 1 ASan job in multi-core setup |
| Stack exhaustion | Increase stack with ASAN_OPTIONS=stack_size=... |
| GCC version mismatch | Ensure system GCC matches AFL++ plugin version |
See Also: For comprehensive sanitizer configuration and troubleshooting, see the address-sanitizer technique skill.
| Tip | Why It Helps |
|---|---|
| Use LLVMFuzzerTestOneInput harnesses where possible | If a fuzzing campaign has at least 85% stability then this is the most efficient fuzzing style. If not then try standard input or file input fuzzing |
| Use dictionaries | Helps fuzzer discover format-specific keywords and magic bytes |
| Set realistic timeouts | Prevents false positives from system load |
| Limit input size | Larger inputs don't necessarily explore more space |
| Monitor stability | Low stability indicates non-deterministic behavior |
AFL++ can fuzz programs reading from stdin without a libFuzzer harness:
./afl++ docker afl-clang-fast++ -O2 main_stdin.c -o fuzz_stdin
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzz_stdinThis is slower than persistent mode but requires no harness code.
For programs that read files, use @@ placeholder:
./afl++ docker afl-clang-fast++ -O2 main_file.c -o fuzz_file
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzz_file @@For better performance, use fmemopen to create file descriptors from memory.
Fuzz command-line arguments using argv-fuzz-inl.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __AFL_COMPILER
#include "argv-fuzz-inl.h"
#endif
void check_buf(char *buf, size_t buf_len) {
if(buf_len > 0 && buf[0] == 'a') {
if(buf_len > 1 && buf[1] == 'b') {
if(buf_len > 2 && buf[2] == 'c') {
abort();
}
}
}
}
int main(int argc, char *argv[]) {
#ifdef __AFL_COMPILER
AFL_INIT_ARGV();
#endif
if (argc < 2) {
fprintf(stderr, "Usage: %s <input_string>\n", argv[0]);
return 1;
}
char *input_buf = argv[1];
size_t len = strlen(input_buf);
check_buf(input_buf, len);
return 0;
}Download the header:
curl -O https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/argv_fuzzing/argv-fuzz-inl.hCompile and run:
./afl++ docker afl-clang-fast++ -O2 main_arg.c -o fuzz_arg
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzz_arg| Setting | Impact |
|---|---|
| CPU core count | Linear scaling with physical cores |
| Persistent mode | 10-20x faster than fork server |
-G input size limit | Smaller = faster, but may miss bugs |
| ASan ratio | 1 ASan job per 4-8 non-ASan jobs |
| Problem | Cause | Solution |
|---|---|---|
| Low exec/sec (<1k) | Not using persistent mode | Create a LLVMFuzzerTestOneInput style harness |
| Low stability (<85%) | Non-deterministic code | Fuzz a program via stdin or file inputs, or create such a harness |
| GCC plugin error | GCC version mismatch | Ensure system GCC matches AFL++ build and install gcc-$GCC_VERSION-plugin-dev |
| No crashes found | Need sanitizers | Recompile with AFL_USE_ASAN=1 |
| Memory limit exceeded | ASan uses 20TB virtual | Remove -m flag when using ASan |
| Docker performance loss | Virtualization overhead | Use bare metal or VM for production fuzzing |
| Skill | Use Case |
|---|---|
| fuzz-harness-writing | Detailed guidance on writing effective harnesses |
| address-sanitizer | Memory error detection during fuzzing |
| undefined-behavior-sanitizer | Detect undefined behavior bugs |
| fuzzing-corpus | Building and managing seed corpora |
| fuzzing-dictionaries | Creating dictionaries for format-aware fuzzing |
| Skill | When to Consider |
|---|---|
| libfuzzer | Quick prototyping, single-threaded fuzzing is sufficient |
| libafl | Need custom mutators or research-grade features |
AFL++ GitHub Repository Official repository with comprehensive documentation, examples, and issue tracker.
Fuzzing in Depth Advanced documentation by the AFL++ team covering instrumentation modes, optimization techniques, and advanced use cases.
AFL++ Under The Hood Technical deep-dive into AFL++ internals, mutation strategies, and coverage tracking mechanisms.
AFL++: Combining Incremental Steps of Fuzzing Research Research paper describing AFL++ architecture and performance improvements over original AFL.
© trailofbits, CC-BY-SA-4.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files (assets) in plugins/testing-handbook-skills/skills/aflpp of trailofbits/skills.
Open the folder on GitHubat commit 82fe822
Aflpp next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Aflpp this skilltrailofbits/skills | 7.4k | — | ~5.6k | Automated safety check: Pass | CC-BY-SA-4.0 | |
| Code Audit3stoneBrother/code-audit | 893 | 1 repos | ~2.7k | Automated safety check: Pass | None | |
| Harness Design Fuzzingprovos/ironcurtain | 613 | — | ~5.7k | Automated safety check: Pass | Apache-2.0 | |
| ClusterfuzzliteInternationalColorConsortium/iccDEV | 183 | — | ~1.5k | Automated safety check: Pass | BSD-3-Clause | |
| Audit Native Memory Safetycyberful/cyberful | 134 | — | ~829 | Automated safety check: Pass | AGPL-3.0 | |
| Fuzzingmohitmishra786/low-level-dev-skills | 253 | — | ~2.1k | Automated safety check: Pass | MIT |
3stoneBrother/code-audit
Professional code security audit skill covering 55+ vulnerability types.
provos/ironcurtain
Reference vocabulary for designing instrumented harnesses that drive vulnerability discovery — design classes (trigger-driven vs coverage-driven), tiered scope (T1 isolated function / T2…
InternationalColorConsortium/iccDEV
Build, test, or update the iccDEV ClusterFuzzLite libFuzzer integration across ASan, UBSan, and MSan.
cyberful/cyberful
Audit C, C++, unsafe Rust, native extensions, parsers, codecs, FFI boundaries, and systems code for memory corruption and low-level exploitation risk.
mohitmishra786/low-level-dev-skills
Fuzzing skill for automated input-driven bug finding in C/C++.
ayutaz/piper-plus
Python canonical (src/pythonrun/piperplus/, src/python/pipertrain/, src/python/g2p/piperplusg2p/) を変更した PR で、 ONNX I/O 以外の追随漏れ (phonemizer / config schema / CLI flag / data 形式 / API 変更) を 7 ランタイム +…
trailofbits/skills
Scans a codebase for vulnerabilities with CodeQL's data flow and taint tracking in run-all or important-only modes, including data extensions for project-specific sources and sinks.
trailofbits/skills
Generates Mermaid diagrams from Trailmark code graphs, including call graphs, class hierarchies, module dependency maps, complexity heatmaps and attack surface data flows.
trailofbits/skills
Compares Trailmark code graphs at two snapshots, such as commits, tags or directories, to surface attack paths, blast radius and taint changes that text diffs miss.
trailofbits/skills
Draws a 12 Houses tarot spread to break ties when a request is vague or casually delegated, then reads the cards to pick the next step.
trailofbits/skills
Detects languages, proposes rulesets for approval, then runs the approved Semgrep scan across a codebase and merges the output into one SARIF file.
trailofbits/skills
Searches and extracts data from Burp Suite project files on the command line: regex searches over responses, audit findings, proxy history and site map data.
Categories
Sets up and runs AFL++ for multi-core fuzzing of C/C++ projects built with afl-clang-fast or afl-gcc-fast. Aflpp is an agent skill from trailofbits/skills, published by the product's own GitHub organization. Sets up and runs AFL++ for multi-core fuzzing of C/C++ projects built with afl-clang-fast or afl-gcc-fast.
Aflpp fits situations like: scaling fuzzing across cores; fuzzing a mature C/C++ codebase; reading the afl-fuzz status screen; moving on after libFuzzer has plateaued.
Run `npx skills add trailofbits/skills --skill aflpp -a claude-code`. Or copy the skill folder (plugins/testing-handbook-skills/skills/aflpp in trailofbits/skills) into .claude/skills/aflpp in your project. Claude Code loads it when a task matches its description.
Run `npx skills add trailofbits/skills --skill aflpp -a codex`. Or copy the skill folder (plugins/testing-handbook-skills/skills/aflpp in trailofbits/skills) into .agents/skills/aflpp in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add trailofbits/skills --skill aflpp -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/aflpp, .gemini/skills/aflpp, .github/skills/aflpp and .opencode/skills/aflpp in your project.
Going by SKILL.md and its folder, Aflpp needs the command-line tools its instructions call (docker, bash, apt, git and curl). Our summary lists: Docker.
SKILL.md names 7 domains. In commands or code: github.com and raw.githubusercontent.com; the agent is likely to contact these when it follows the instructions. As links in the text: youtube.com, aflplus.plus, blog.ritsec.club, usenix.org and blog.trailofbits.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Aflpp is published under the CC-BY-SA-4.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.6k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Aflpp: Code Audit (3stoneBrother/code-audit, 893 stars), Harness Design Fuzzing (provos/ironcurtain, 613 stars), Clusterfuzzlite (InternationalColorConsortium/iccDEV, 183 stars) and Audit Native Memory Safety (cyberful/cyberful, 134 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
trailofbits (a GitHub organization, an official publisher) maintains it in trailofbits/skills, which has 7,400 GitHub stars. The repository holds 79 skills in this directory. The repository was last updated on October 2, 2026.
Source: trailofbits/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.