agentsclimarketplace

Secure fuzz testing

Skill roedyrustam/claudevibeskills/src/secure-fuzz-testing

Koleksi 20 Claude Skills siap pakai untuk pengembangan SaaS, web modern, dan praktik rekayasa perangkat lunak tingkat lanjut.

Install
npx -y skills add roedyrustam/claudevibeskills --skill secure-fuzz-testing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Coverage-guided fuzzing with Atheris, cargo-fuzz, and native Go fuzzing, combined with compilers/sanitizers (ASan, MSan, UBSan) for security validation. Use whenever the user wants to fuzz test code, find memory safety bugs, validate parsers/deserializers against malformed input, or harden security-critical code paths. Trigger on mentions of fuzzing, fuzz testing, AddressSanitizer, libFuzzer, cargo-fuzz, Atheris, go test -fuzz, or security validation of parsing/deserialization logic.

SKILL.md

9.0 KB, as published. Nobody here has run it

Secure Fuzz Testing

Coverage-guided fuzzing across Python, Rust, and Go with sanitizer integration.


Why Fuzz

Fuzzing finds bugs unit tests miss: crashes, panics, memory corruption, infinite loops, and logic errors triggered by malformed or unexpected input. Critical for any code that parses untrusted input — file formats, network protocols, deserializers, APIs.


Python Fuzzing with Atheris

Setup

uv add --dev atheris

Basic Fuzz Harness

# fuzz/fuzz_parser.py
import atheris
import sys

with atheris.instrument_imports():
    from myapp.parser import parse_config

def TestOneInput(data: bytes) -> None:
    fdp = atheris.FuzzedDataProvider(data)
    text = fdp.ConsumeUnicodeNoSurrogates(fdp.remaining_bytes())

    try:
        parse_config(text)
    except (ValueError, KeyError):
        pass  # Expected exceptions — not bugs
    # Anything else (TypeError, IndexError, unhandled) = potential bug

atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
# Run fuzzing
python fuzz/fuzz_parser.py

# With a corpus directory (saves interesting inputs)
mkdir corpus
python fuzz/fuzz_parser.py corpus/

# Limit runtime
python fuzz/fuzz_parser.py -max_total_time=300  # 5 minutes

# Reproduce a crash
python fuzz/fuzz_parser.py crash-<hash>

Structured Fuzzing (JSON-like inputs)

import atheris
import json

def TestOneInput(data: bytes) -> None:
    fdp = atheris.FuzzedDataProvider(data)

    # Build structured input from fuzz bytes
    payload = {
        "user_id": fdp.ConsumeIntInRange(-1000, 1000000),
        "name": fdp.ConsumeUnicodeNoSurrogates(50),
        "active": fdp.ConsumeBool(),
        "tags": [fdp.ConsumeUnicodeNoSurrogates(20) for _ in range(fdp.ConsumeIntInRange(0, 5))],
    }

    try:
        validate_user_payload(payload)
    except ValidationError:
        pass

atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()

Rust Fuzzing with cargo-fuzz

Setup

cargo install cargo-fuzz
cargo fuzz init

Fuzz Target

// fuzz/fuzz_targets/parse_input.rs
#![no_main]
use libfuzzer_sys::fuzz_target;
use myapp::parser::parse_config;

fuzz_target!(|data: &[u8]| {
    if let Ok(s) = std::str::from_utf8(data) {
        let _ = parse_config(s); // panics are caught and reported as crashes
    }
});

Structured Fuzzing with arbitrary

// fuzz/fuzz_targets/structured.rs
#![no_main]
use libfuzzer_sys::fuzz_target;
use arbitrary::Arbitrary;

#[derive(Arbitrary, Debug)]
struct UserPayload {
    id: u32,
    name: String,
    age: u8,
    tags: Vec<String>,
}

fuzz_target!(|payload: UserPayload| {
    let _ = validate_user(&payload);
});
# fuzz/Cargo.toml
[dependencies]
libfuzzer-sys = "0.4"
arbitrary = { version = "1", features = ["derive"] }
myapp = { path = ".." }

Running with Sanitizers

# AddressSanitizer (default) — detects memory corruption
cargo fuzz run parse_input

# Run for a fixed duration
cargo fuzz run parse_input -- -max_total_time=300

# Run with a larger corpus
cargo fuzz run parse_input fuzz/corpus/parse_input/

# MemorySanitizer — detects uninitialized memory reads
RUSTFLAGS="-Z sanitizer=memory" cargo fuzz run parse_input

# Minimize a crashing input
cargo fuzz tmin parse_input fuzz/artifacts/parse_input/crash-<hash>

# Reproduce a specific crash
cargo fuzz run parse_input fuzz/artifacts/parse_input/crash-<hash>

Go Native Fuzzing

Fuzz Test (Go 1.18+, built-in)

// parser_fuzz_test.go
package parser

import "testing"

func FuzzParseConfig(f *testing.F) {
    // Seed corpus — known valid/edge-case inputs
    f.Add("key=value")
    f.Add("")
    f.Add("key=")
    f.Add(`key="quoted value"`)

    f.Fuzz(func(t *testing.T, input string) {
        result, err := ParseConfig(input)
        if err != nil {
            return // expected error — not a bug
        }

        // Invariant checks
        if result == nil {
            t.Errorf("ParseConfig returned nil with no error for input: %q", input)
        }

        // Round-trip property: parse(serialize(x)) == x
        serialized := result.Serialize()
        reparsed, err := ParseConfig(serialized)
        if err != nil {
            t.Errorf("Failed to reparse serialized output: %v", err)
        }
        if !reparsed.Equals(result) {
            t.Errorf("Round-trip mismatch for input: %q", input)
        }
    })
}
# Run fuzzing
go test -fuzz=FuzzParseConfig -fuzztime=60s

# Run with sanitizer (requires CGO + clang)
go test -fuzz=FuzzParseConfig -fuzztime=60s -gcflags=all=-d=checkptr

# Crashes saved automatically to testdata/fuzz/FuzzParseConfig/
# Re-run with: go test -run=FuzzParseConfig/<seed>

Sanitizers Reference

SanitizerDetectsUse With
ASan (AddressSanitizer)Buffer overflows, use-after-free, double-freeC/C++/Rust
MSan (MemorySanitizer)Uninitialized memory readsC/C++/Rust (Clang)
UBSan (UndefinedBehaviorSanitizer)Integer overflow, null deref, type confusionC/C++/Rust
TSan (ThreadSanitizer)Data races, deadlocksConcurrent code

C/C++ with libFuzzer + Sanitizers

# Compile with multiple sanitizers
clang++ -g -O1 -fsanitize=address,fuzzer,undefined \
  -fsanitize-address-use-after-scope \
  fuzz_target.cc -o fuzz_target

./fuzz_target -max_total_time=300 corpus/

Building Effective Fuzz Harnesses

Good Harness Checklist

  • Targets a single, well-defined function or parsing boundary
  • Catches expected errors (don't report them as crashes)
  • Includes a seed corpus of realistic valid + edge-case inputs
  • Checks invariants, not just "doesn't crash" (round-trip, idempotency)
  • Runs fast (microseconds per iteration) — slow targets fuzz poorly
  • Deterministic — same input always produces same behavior

What to Fuzz First (Priority Order)

  1. Parsers — JSON, YAML, config files, binary formats
  2. Deserializers — anything from bytes → struct
  3. Network protocol handlers — anything reading from sockets
  4. Compression/decompression — zip, gzip bombs, decompression ratio attacks
  5. Auth token / JWT parsing — malformed tokens shouldn't panic
  6. Regular expressions — catastrophic backtracking (ReDoS)
  7. Path/URL handling — path traversal via malformed input

CI Integration

# .github/workflows/fuzz.yml
name: Fuzz Testing

on:
  schedule:
    - cron: '0 2 * * *'  # nightly
  pull_request:
    paths:
      - 'src/parser/**'

jobs:
  fuzz-rust:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@nightly
      - run: cargo install cargo-fuzz
      - name: Run fuzz targets (5 min each)
        run: |
          for target in $(cargo fuzz list); do
            cargo fuzz run $target -- -max_total_time=300
          done

  fuzz-go:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
      - name: Run Go fuzz tests
        run: go test -fuzz=Fuzz -fuzztime=60s ./...

Triaging Fuzz Findings

# 1. Minimize the crashing input (find smallest reproducer)
cargo fuzz tmin <target> <crash-file>

# 2. Get a backtrace
RUST_BACKTRACE=full cargo fuzz run <target> <crash-file>

# 3. Classify the bug:
#    - Panic/crash → DoS risk, fix immediately
#    - Memory corruption (ASan) → CRITICAL, potential RCE
#    - Logic error (wrong output, no crash) → correctness bug
#    - Infinite loop/hang → DoS risk (add timeout, fix complexity)

# 4. Write a regression test from the minimized crash
#    Add the crashing input to your seed corpus permanently

Key Rules

  1. Fuzz parsers and deserializers first — highest bug density, highest risk
  2. Catch expected errors in the harness — don't waste cycles on known-invalid input paths
  3. Always minimize crashes before filing/fixing — smaller reproducers are easier to debug
  4. Run ASan by default — it's nearly free and catches the most dangerous bugs
  5. Seed corpus matters — start fuzzing from realistic inputs, not just empty/random
  6. Check invariants, not just crashes — round-trip properties catch logic bugs
  7. Time-box CI fuzzing — 1-5 min per target in PR CI, longer runs nightly
  8. Every fixed crash becomes a permanent corpus entry — prevents regression
  9. Fuzz before every major release — especially after touching parsing code
  10. Treat OOM and timeouts as bugs too — not just crashes/panics

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.