
Fuzz Testing in CI/CD with AFL++
FreeIntegrate AFL++ fuzz testing into your CI/CD pipeline.
Free · Opens the source repo
What Fuzz Testing in CI/CD with AFL++ does
This skill provides a comprehensive integration of AFL++ (American Fuzzy Lop Plus Plus) into CI/CD pipelines, aimed at enhancing the security testing of C/C++ applications. AFL++ is a powerful fuzz testing tool that employs coverage-guided techniques to discover vulnerabilities by mutating inputs and tracking code paths. By using this skill, developers can automate the process of identifying memory corruption and input handling vulnerabilities, significantly improving the security posture of their applications.
The skill walks users through the necessary steps to set up AFL++ in a CI/CD environment, including harness construction, instrumentation builds, and configuration for persistent fuzzing. It covers essential prerequisites such as the need for a Linux-based CI runner, a compatible compiler toolchain, and a seed corpus of valid inputs. The detailed workflows provided in the skill guide users through building fuzzing harnesses, compiling with AFL++ instrumentation, and integrating fuzz testing into their CI/CD processes using tools like GitHub Actions.
By leveraging AFL++'s capabilities, this skill enables continuous testing of various components such as parsers and protocol handlers, ensuring that any untrusted input is rigorously tested. This proactive approach to security testing allows teams to catch vulnerabilities early in the development cycle, thereby reducing the risk of security issues in production environments.
Overall, this skill is particularly beneficial for developers and security engineers looking to enhance their CI/CD workflows with automated fuzz testing, ensuring robust security measures are in place throughout the software development lifecycle.
When to use it
Use this skill when you need to implement fuzz testing in your CI/CD pipeline, particularly for C/C++ applications.
When not to use it
This skill is not suitable for projects that do not use C/C++ or for CI/CD environments that are not Linux-based.
What you can build with it
Automating Security Testing
Integrate fuzz testing into your CI/CD pipeline to automatically identify vulnerabilities during the development process.
Enhancing Compliance Measures
Use this skill to implement security controls that align with compliance requirements for software development.
Improving Application Security
Conduct security assessments by incorporating fuzz testing to discover memory-safety bugs in your applications.
How to install Fuzz Testing in CI/CD with AFL++
View source1. Install with the skills CLI
npx skills add mukul975/anthropic-cybersecurity-skills/implementing-fuzz-testing-in-cicd-with-aflplusplus --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by mukul975Implementing Fuzz Testing in CI/CD with AFL++
Overview
AFL++ (American Fuzzy Lop Plus Plus) is a community-maintained fork of AFL that provides state-of-the-art coverage-guided fuzz testing for discovering vulnerabilities in compiled applications. AFL++ uses genetic algorithms to mutate inputs, tracking code coverage to find new execution paths that trigger crashes, hangs, and undefined behavior. In CI/CD environments, AFL++ can be integrated to continuously test parsers, protocol handlers, file format processors, and any code that handles untrusted input. AFL++ supports persistent mode for high-speed fuzzing (up to 100,000+ executions per second), custom mutators, QEMU mode for binary-only fuzzing, and CmpLog/RedQueen for automatic dictionary extraction.
When to Use
- When deploying or configuring implementing fuzz testing in cicd with aflplusplus capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- Linux-based CI runners (AFL++ does not support Windows natively)
- GCC or Clang compiler toolchain
- AFL++ installed (
apt install aflplusplusor built from source) - Target application with harness functions isolating input processing
- Seed corpus of valid input samples
Core Concepts
Coverage-Guided Fuzzing
AFL++ instruments the target binary at compile time (or via QEMU/Frida for binary-only targets) to track which code paths each input exercises. When a mutated input triggers a new code path, it is saved to the corpus for further mutation. This feedback loop enables AFL++ to systematically explore program state space.
Instrumentation Modes
| Mode | Use Case | Performance |
|---|---|---|
afl-clang-fast (LTO) | Source available, best performance | Highest |
afl-clang-fast | Source available, standard | High |
afl-gcc-fast | GCC-based projects | High |
QEMU mode | Binary-only, no source | Medium |
Frida mode | Binary-only, cross-platform | Medium |
Unicorn mode | Firmware, embedded | Low |
Persistent Mode
Persistent mode avoids fork overhead by fuzzing within a loop:
#include <unistd.h>
__AFL_FUZZ_INIT();
int main() {
__AFL_INIT();
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
while (__AFL_LOOP(10000)) {
int len = __AFL_FUZZ_TESTCASE_LEN;
// Process buf[0..len-1]
parse_input(buf, len);
}
return 0;
}
Workflow
Step 1 --- Build the Fuzzing Harness
Create a harness that feeds AFL++ input to the target function:
// fuzz_harness.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "target_parser.h"
__AFL_FUZZ_INIT();
int main() {
__AFL_INIT();
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
while (__AFL_LOOP(10000)) {
int len = __AFL_FUZZ_TESTCASE_LEN;
if (len < 4) continue;
// Reset state between iterations
parser_context_t ctx;
parser_init(&ctx);
parser_process(&ctx, buf, len);
parser_cleanup(&ctx);
}
return 0;
}
Step 2 --- Compile with AFL++ Instrumentation
# Standard instrumentation
export CC=afl-clang-fast
export CXX=afl-clang-fast++
# Enable AddressSanitizer for better crash detection
export AFL_USE_ASAN=1
# Build the target with instrumentation
$CC -o fuzz_harness fuzz_harness.c -ltarget_parser -fsanitize=address
# Build a CmpLog binary for better coverage
$CC -o fuzz_harness_cmplog fuzz_harness.c -ltarget_parser \
-fsanitize=address -DCMPLOG
Step 3 --- Prepare Seed Corpus
mkdir -p corpus/
# Add valid input samples
cp test_inputs/* corpus/
# Minimize the corpus
afl-cmin -i corpus/ -o corpus_min/ -- ./fuzz_harness @@
# Further minimize individual inputs
mkdir -p corpus_tmin/
for f in corpus_min/*; do
afl-tmin -i "$f" -o "corpus_tmin/$(basename $f)" -- ./fuzz_harness @@
done
Step 4 --- Configure CI/CD Integration
GitHub Actions:
name: Fuzz Testing
on:
push:
branches: [main]
schedule:
- cron: '0 2 * * *' # Nightly fuzzing
jobs:
fuzz:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@v4
- name: Install AFL++
run: |
sudo apt-get update
sudo apt-get install -y aflplusplus
- name: Restore corpus cache
uses: actions/cache@v4
with:
path: corpus/
key: fuzz-corpus-${{ github.sha }}
restore-keys: fuzz-corpus-
- name: Build fuzzing harness
run: |
export CC=afl-clang-fast
export AFL_USE_ASAN=1
make fuzz_harness
- name: Run AFL++ fuzzing (CI mode)
env:
AFL_CMPLOG_ONLY_NEW: 1
AFL_FAST_CAL: 1
AFL_NO_STARTUP_CALIBRATION: 1
run: |
mkdir -p findings/
timeout 7200 afl-fuzz \
-S ci_fuzzer \
-i corpus/ \
-o findings/ \
-t 5000 \
-- ./fuzz_harness @@ || true
- name: Check for crashes
run: |
CRASHES=$(find findings/ -path "*/crashes/*" -not -name "README.txt" | wc -l)
echo "Found $CRASHES unique crashes"
if [ "$CRASHES" -gt 0 ]; then
echo "::error::AFL++ found $CRASHES crashes"
for crash in findings/*/crashes/*; do
[ -f "$crash" ] && echo "Crash: $crash ($(wc -c < $crash) bytes)"
done
exit 1
fi
- name: Update corpus cache
if: always()
run: |
afl-cmin -i findings/ci_fuzzer/queue/ -o corpus/ -- ./fuzz_harness @@
Step 5 --- Parallel Fuzzing for Nightly Runs
# Launch multiple secondary instances for better coverage
for i in $(seq 1 $(nproc)); do
afl-fuzz -S fuzzer_$i \
-i corpus/ \
-o findings/ \
-- ./fuzz_harness @@ &
done
# Wait for all fuzzers
wait
# Merge and minimize corpus
afl-cmin -i findings/*/queue/ -o corpus_merged/ -- ./fuzz_harness @@
Step 6 --- Crash Triage
# Reproduce and categorize crashes
for crash in findings/*/crashes/*; do
echo "=== Testing: $crash ==="
timeout 5 ./fuzz_harness_asan "$crash" 2>&1 | head -20
echo "---"
done
# Deduplicate crashes by stack trace
afl-collect findings/ crashes_deduped/ -- ./fuzz_harness @@
CI/CD Best Practices for AFL++
| Setting | CI Short Run | Nightly Long Run |
|---|---|---|
| Duration | 30-60 min | 4-24 hours |
| Mode | -S (secondary only) | -S (no -M for CI) |
AFL_CMPLOG_ONLY_NEW | 1 | 1 |
AFL_FAST_CAL | 1 | 0 |
AFL_NO_STARTUP_CALIBRATION | 1 | 0 |
| Corpus caching | Required | Required |
| Parallel instances | 1-2 | nproc |
Monitoring Fuzzing Campaigns
# View fuzzing statistics
afl-whatsup findings/
# Key metrics to track:
# - Total paths found (code coverage indicator)
# - Unique crashes / unique hangs
# - Stability percentage (should be >90%)
# - Exec speed (execs/sec)
# - Cycles done (full corpus cycles completed)
References
Frequently asked questions about Fuzz Testing in CI/CD with AFL++
Similar skills
GitHub Actions Hardening
Enhance the security of your GitHub Actions workflows.
Sensitive Logging Audit
Audit and fix sensitive data exposure in Python logging.
Android App Static Analysis
Automate security assessments of Android apps with MobSF.
Integrating DAST with OWASP ZAP
Seamlessly integrate dynamic security testing into CI/CD pipelines.
Implementing Runtime Security with Tetragon
Enhance Kubernetes security with eBPF-based observability.
Implementing Mobile Application Management
Secure enterprise data on mobile devices with app-level controls.
