본문으로 건너뛰기
cccskills
무료GitHub에 공개

fuzzing

Use when planning an end-to-end fuzzing program for a project: engine and target selection, corpus management, and CI or nightly wiring. Not for harness design: use fuzz-harness-writing. Not for engine operation or triage: use libfuzzer. Not for sanitizer flag reference: use sanitizers.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(3)

  • SKILL.md7.2 KB
  • agents/openai.yaml197 B
  • references/targets.md5.7 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Fuzzing

Contract

FieldBound contract
TriggerCoverage-guided fuzz testing for a parser, deserializer, codec, or API boundary: harness writing, libFuzzer or AFL++ setup, corpus management, crash reproduction, or CI runs.
AuthorityReversible local. Writes are limited to fuzz binaries, corpora, dictionaries, findings, and logs under the project tree; rollback is deleting those directories. No remote mutation.
Side effectBuilt fuzz targets, corpus directories, crash artifacts, and coverage measurements.
DoneA fuzz target runs against a seeded corpus, the crash or clean verdict is reproduced on demand, and the CI or nightly plan is written down.

Inputs

  1. Target code (required): the library or entry point to fuzz, ideally a parse or I/O boundary.
  2. Seeds (required when they exist): known-good inputs from tests or real traffic.
  3. Toolchain (required): Clang for libFuzzer; AFL++ installed for fork-mode fuzzing. Grounded channels: Clang 23.1.0, AFL++ v5.03c (AGPL 3.0+ since v5.00c, mixed licensing in the repo).
  4. Time budget (optional): seconds for CI regression runs, hours for nightly.

Procedure

  1. Write the target as a function of arbitrary bytes. The harness owns every guarantee:
// fuzz_parser.c
#include <stdint.h>
#include <stddef.h>
#include "myparser.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    MyParser *p = parser_create();
    if (p) {
        parser_feed(p, (const char *)data, size);
        parser_destroy(p);
    }
    return 0;
}

Rules: return 0 for uninteresting input instead of exiting; never call abort or exit; never read or write outside [data, data + size); keep no state between calls; stay fast, since the fuzzer calls it millions of times. Done when: the harness passes a review against each rule. 2. Build with libFuzzer and the sanitizer set. -fsanitize=fuzzer links libFuzzer and supplies main, so the target must not define one:

clang -fsanitize=fuzzer,address,undefined -fno-omit-frame-pointer -g -O1 \
    fuzz_parser.c myparser.c -o fuzz_parser

Done when: the binary links without a duplicate main and runs -help=1 cleanly. 3. Seed and run:

mkdir -p corpus
cp tests/inputs/* corpus/          # real seeds sharply cut time to coverage
./fuzz_parser corpus/ -max_len=65536 -timeout=10
./fuzz_parser corpus/ -max_total_time=3600
./fuzz_parser corpus/ -jobs=4 -workers=4

Defaults worth knowing: -max_len 4096 when unset, -timeout 1200 seconds, -rss_limit_mb 2048, -error_exitcode 77, -len_control 100. Workers default to half the core count when unset. Done when: the run starts consuming the corpus and reporting new coverage. 4. Reproduce and minimize every finding. Artifacts land as crash-<hash>, oom-<hash>, or timeout-<hash> in the artifact prefix directory:

./fuzz_parser crash-abc123                 # reproduce
./fuzz_parser -minimize_crash=1 -max_total_time=60 crash-abc123

Re-run the minimized case under gdb (gdb --args ./fuzz_parser crash-min) to name the faulting frame. Done when: one small input reproduces the bug deterministically. 5. Add AFL++ where process-level isolation or non-library targets are needed:

afl-clang-fast -g -O1 -o prog_afl main.c myparser.c
afl-fuzz -i afl-input -o afl-output -- ./prog_afl @@    # @@ = input file path
afl-fuzz -i afl-input -o afl-output -- ./prog_afl       # stdin target: drop @@

Persistent mode avoids a fork per input and raises throughput for library targets; __AFL_LOOP(1000) bounds each iteration batch. Scale out with -M main plus one -S name instance per spare core, and read status with afl-whatsup afl-output. Done when: at least one AFL++ instance reports stable cycles with new paths. 6. Manage the corpus as an asset. Merge runs to the coverage-unique subset, and keep the corpus in version control or CI cache:

./fuzz_parser -merge=1 corpus_min/ corpus/ run1/ run2/
afl-cmin -i afl-output/default/queue -o corpus_min -- ./prog_afl @@
./fuzz_parser corpus/ -runs=0 -print_coverage=1     # coverage of the corpus

Done when: one minimized corpus exists and reproduces the union of coverage. 7. Guide mutation with a dictionary when the format has tokens:

# parser.dict
kw1="<"
kw2=">"
null_byte="\x00"
magic1="\x89PNG"
./fuzz_parser corpus/ -dict=parser.dict
afl-fuzz -i corpus/ -o out/ -x parser.dict -- ./prog_afl @@

For structured formats that checksum or length-prefix, implement LLVMFuzzerCustomMutator and repair the invariant after LLVMFuzzerMutate, or the fuzzer never passes the header. Done when: deep paths are reached without human-crafted inputs. 8. Wire CI as a fixed-time regression, not an open-ended run:

- name: Build fuzz target
  run: |
    clang -fsanitize=fuzzer,address,undefined -g -O1 \
      fuzz_parser.c myparser.c -o fuzz_parser
- name: Fuzz regression (60 seconds)
  run: |
    ./fuzz_parser corpus/ -max_total_time=60 -error_exitcode=1 \
      -artifact_prefix=artifacts/
- name: Reproduce known crashes
  run: |
    for f in known_crashes/*; do ./fuzz_parser "$f" || exit 1; done

Longer campaigns go to scheduled jobs with -max_total_time=3600 or to OSS-Fuzz infrastructure. Done when: a pull request cannot merge with a target that regresses. 9. Add Python targets with Atheris, and Zig targets through the built-in fuzzer (Zig 0.13 and later):

import atheris, sys

with atheris.instrument_imports():
    import myparser

def TestOneInput(data: bytes) -> None:
    fdp = atheris.FuzzedDataProvider(data)
    try:
        myparser.parse(fdp.ConsumeString(sys.maxsize))
    except myparser.ParseError:
        pass

if __name__ == "__main__":
    atheris.Setup(sys.argv, TestOneInput)
    atheris.Fuzz()
zig build test --fuzz

Done when: each language boundary has its own target or a recorded decision not to fuzz it.

Harness templates and the full flag tables live in references/targets.md.

Failure and recovery

Failure classBehavior
Fuzzer finds no coverage growthThe harness or sanitizer set blocks depth. Check that -fsanitize=fuzzer is in the build and seeds are real inputs.
Crash does not reproduceThe bug depends on corpus state or is flaky. Re-run the single input ten times; check for uninitialized reads (initcheck) or a race.
OOM artifacts flood the runLower -rss_limit_mb, cap -max_len, or bound allocations inside the harness.
AFL++ target dies at startupMemory limit too low for the target. Raise -m or add -t for slow inputs.
CI run too slowShrink -max_total_time, run -workers=$(nproc), and cache the corpus between runs.
Fuzzer slows to a crawl mid-runThe target leaks or retains state between calls. Audit the harness against the step 1 rules.

Output

The built targets, the seeded and minimized corpora, the crash reproduction commands, and the CI configuration. Every finding carries its minimized artifact and the sanitizer report that explains it.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when configuring ADC sampling time, DMA-driven ADC, calibration, or DAC channel setup on bare-metal MCUs. Not for the DMA stream itself: use dma-baremetal.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

af-xdp

무료

Use when creating AF_XDP sockets, configuring UMEM and XSK rings, writing an XDP redirect program, or choosing copy versus zero-copy mode. Not for full kernel bypass: use dpdk.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when a redacted, trimmed agent transcript must be appended to a GitHub PR or issue body, with human approval and preview. Not for automated or model-initiated insertion.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

agents-md

무료

Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential, publish, deploy, or irreversible changes.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

OutlineDriven의 스킬 모두 보기

이 스킬의 문제 신고