secure-fuzz-testing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited secure-fuzz-testing (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Coverage-guided fuzzing across Python, Rust, and Go with sanitizer integration.
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.
uv add --dev atheris# 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>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()cargo install cargo-fuzz
cargo fuzz init// 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
}
});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 = ".." }# 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>// 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>| Sanitizer | Detects | Use With |
|---|---|---|
| ASan (AddressSanitizer) | Buffer overflows, use-after-free, double-free | C/C++/Rust |
| MSan (MemorySanitizer) | Uninitialized memory reads | C/C++/Rust (Clang) |
| UBSan (UndefinedBehaviorSanitizer) | Integer overflow, null deref, type confusion | C/C++/Rust |
| TSan (ThreadSanitizer) | Data races, deadlocks | Concurrent code |
# 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/bytes → struct# .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 ./...# 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~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.