implementing-fuzz-testing-in-cicd-with-aflplusplus skill (Anthropic-Cybersecurity-Skills)

From Public Agent Wiki

What it does. Integrates AFL++ coverage-guided fuzzing into CI/CD pipelines, covering harness construction, AFL++/AddressSanitizer/CmpLog instrumentation builds, and persistent-mode fuzzing to discover memory-corruption and input-handling vulnerabilities in C/C++ code. Use when adding automated fuzz testing to a build pipeline or hunting for memory-safety bugs in native/compiled applications. Part of mukul975/Anthropic-Cybersecurity-Skills (817 security skills) (mukul975/Anthropic-Cybersecurity-Skills).

Upstream mukul975/Anthropic-Cybersecurity-Skills
Skill file skills/implementing-fuzz-testing-in-cicd-with-aflplusplus/SKILL.md
License Apache-2.0 (skill folder LICENSE)
Author mukul975
Fetched 2026-09-10

Install

  • npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill implementing-fuzz-testing-in-cicd-with-aflplusplus, or copy the skill folder into ~/.claude/skills/implementing-fuzz-testing-in-cicd-with-aflplusplus/.
  • Raw file: curl -sL https://raw.githubusercontent.com/mukul975/Anthropic-Cybersecurity-Skills/HEAD/skills/implementing-fuzz-testing-in-cicd-with-aflplusplus/SKILL.md

SKILL.md (verbatim)

name: implementing-fuzz-testing-in-cicd-with-aflplusplus
description: Integrates AFL++ coverage-guided fuzzing into CI/CD pipelines, covering harness construction, AFL++/AddressSanitizer/CmpLog instrumentation builds, and persistent-mode fuzzing to discover memory-corruption and input-handling vulnerabilities in C/C++ code. Use when adding automated fuzz testing to a build pipeline or hunting for memory-safety bugs in native/compiled applications.
domain: cybersecurity
subdomain: devsecops
tags:
- aflplusplus
- fuzz-testing
- cicd
- coverage-guided-fuzzing
- security-testing
- vulnerability-discovery
- afl
version: '1.0'
author: mahipal
license: Apache-2.0
nist_ai_rmf:
- MEASURE-2.7
- MAP-5.1
- MANAGE-2.4
atlas_techniques:
- AML.T0070
- AML.T0066
- AML.T0082
nist_csf:
- PR.PS-01
- GV.SC-07
- ID.IM-04
- PR.PS-04
mitre_attack:
- T1195
- T1554
- T1059.004
- T1005
- T1059

Implementing 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 aflplusplus or 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

Other files in this skill

assets/template.md (verbatim)

Fuzz Testing Implementation Template

Target Application

Field Value
Application Name
Target Function
Language [ ] C [ ] C++ [ ] Other
Input Type [ ] File [ ] Network [ ] Stdin

Fuzzing Configuration

Parameter Value
Instrumentation [ ] afl-clang-fast [ ] afl-gcc-fast [ ] QEMU
Sanitizer [ ] ASan [ ] UBSan [ ] MSan [ ] TSan
Mode [ ] Persistent [ ] Fork
CmpLog [ ] Enabled [ ] Disabled
Timeout per exec ms
CI run duration minutes
Nightly duration hours

Corpus Management

Item Location
Seed corpus
Minimized corpus
CI cache key

Crash Tracking

Crash ID CWE Severity Crash File Stack Trace Summary Fix Status

references/api-reference.md (verbatim)

API Reference — Implementing Fuzz Testing in CI/CD with AFL++

Libraries Used

  • subprocess: Execute AFL++ toolchain commands (afl-clang-fast, afl-fuzz, afl-cmin)
  • pathlib: File system operations for corpus and crash management

CLI Interface

python agent.py compile --source target.c --output target_fuzz [--compiler afl-clang-fast]
python agent.py fuzz --binary ./target_fuzz --input seeds/ --output findings/ [--duration 300]
python agent.py triage --binary ./target_fuzz --crashes-dir findings/default/crashes/
python agent.py stats --stats-file findings/default/fuzzer_stats

Core Functions

compile_target(source_file, output_binary, compiler)

Compiles target with AFL++ instrumentation. Sets AFL_HARDEN=1 for memory sanitizers.

run_fuzzer(binary, input_dir, output_dir, duration_seconds, memory_limit)

Runs afl-fuzz with headless mode (AFL_NO_UI=1), time-limited (-V flag).

Environment Variables Set:

Variable Value Purpose
AFL_SKIP_CPUFREQ 1 Skip CPU frequency check (CI/CD)
AFL_NO_UI 1 Headless mode for CI environments
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES 1 Continue on crash dir issues

parse_fuzzer_stats(stats_file)

Parses AFL++ fuzzer_stats file. Key metrics: execs_per_sec, paths_total, saved_crashes, bitmap_cvg.

triage_crashes(binary, crashes_dir)

Re-runs crash inputs through the binary and classifies by signal (SIGSEGV, SIGABRT, etc.).

minimize_corpus(binary, input_dir, output_dir, timeout)

Runs afl-cmin to remove redundant seeds from the corpus.

AFL++ Commands Used

Command Purpose
afl-clang-fast Compile with LLVM-based instrumentation
afl-fuzz -i <in> -o <out> -- <binary> Main fuzzing loop
afl-cmin -i <in> -o <out> -- <binary> Corpus minimization
afl-tmin -i <crash> -o <min> -- <binary> Test case minimization

Dependencies

AFL++ must be installed: apt install aflplusplus or build from source.

pip install  # No Python packages needed beyond stdlib

references/standards.md (verbatim)

Standards Reference for Fuzz Testing

NIST SP 800-53 Rev 5 Controls

Control Description Fuzzing Alignment
SA-11(5) Penetration Testing Fuzz testing discovers vulnerabilities through automated input mutation
SA-11(8) Dynamic Code Analysis AFL++ provides runtime analysis with instrumented binaries
SI-10 Information Input Validation Fuzzing validates input handling robustness
SI-17 Fail-Safe Procedures Crash detection ensures failures are handled safely

OWASP Testing Guide v4.2

  • WSTG-INPV-07: Testing for Input Validation --- AFL++ systematically tests boundary conditions
  • WSTG-ERRH-01: Error Handling --- Crash analysis reveals improper error handling

CWE Categories Commonly Found by Fuzzing

CWE Name AFL++ Detection Method
CWE-120 Buffer Overflow ASan crash on out-of-bounds write
CWE-125 Out-of-Bounds Read ASan crash on invalid read
CWE-416 Use After Free ASan detects freed memory access
CWE-476 NULL Pointer Dereference SIGSEGV on null deref
CWE-190 Integer Overflow UBSan detects arithmetic overflow
CWE-787 Out-of-Bounds Write ASan detects heap/stack buffer overflow
CWE-400 Uncontrolled Resource Consumption Timeout detection for hangs

Fuzzing Maturity Levels

Level Description CI Integration
1 Basic Manual ad-hoc fuzzing None
2 Structured Harness-based with corpus management PR-triggered short runs
3 Continuous Nightly campaigns with crash tracking Nightly + corpus caching
4 Optimized Multi-tool (AFL++, libFuzzer), crash dedup, coverage tracking Full CI/CD integration with gating

references/workflows.md (verbatim)

AFL++ Fuzz Testing Workflows

Workflow 1: CI Pipeline Integration

Code pushed to branch
       |
Fuzzing harness compiled with afl-clang-fast + ASan
       |
Corpus restored from CI cache
       |
AFL++ runs in secondary mode for fixed duration
       |
[No crashes] --> Corpus updated in cache, pipeline passes
[Crashes found] --> Pipeline fails, crash artifacts uploaded
       |
Developer triages crashes
       |
Fix applied, re-run confirms no regression

Workflow 2: Nightly Fuzzing Campaign

Scheduled nightly trigger (cron)
       |
Build instrumented binary + CmpLog binary
       |
Restore merged corpus from last run
       |
Launch parallel AFL++ instances (nproc count)
       |
Run for 4-8 hours
       |
Collect results from all instances
       |
afl-cmin merges and minimizes corpus
       |
Deduplicate crashes by stack hash
       |
New crashes create Jira/GitHub issues automatically
       |
Updated corpus cached for next run

Workflow 3: Crash Triage and Fix

Crash file identified in findings/
       |
Reproduce crash with ASan-instrumented binary
       |
Capture ASan stack trace and error type
       |
Minimize crash input with afl-tmin
       |
Identify root cause from stack trace
       |
Develop fix and add crash input as regression test
       |
Verify fix by re-running AFL++ with crash input
       |
Update corpus to include edge case inputs

Back to mukul975/Anthropic-Cybersecurity-Skills (817 security skills) or Agent skills.