Skip to content
cccskills
FreePublished on GitHub

atheris

Use when a user needs coverage-guided fuzzing for Python code or a Python native extension using Atheris. Not for remote, credential, publish, deploy, or irreversible changes.

The English summary is being prepared. Showing the original description.

See how to install

Files included (2)

  • SKILL.md8.4 KB
  • agents/openai.yaml166 B

SKILL.md (original)

Review the instructions the agent will receive before you install.

Atheris

Contract

FieldBound contract
TriggerUser needs coverage-guided fuzzing for Python code or a Python native extension using Atheris.
AuthorityReversible local: writes only the Atheris harness file, a corpus directory, and when required for dependency management pyproject.toml and uv.lock in the harness directory; rollback is deleting the harness file and corpus directory and restoring pyproject.toml and uv.lock to their pre-run state. No remote mutation. No source under test is mutated.
Side effectLocal writes: a fuzz.py (or named) harness, a corpus/ directory of seed and crash artifacts, and a transient fuzzing process.
DoneAtheris executes an instrumented target through a deterministic TestOneInput harness, reports coverage, and any saved crash artifact reproduces the same failure when replayed.

Inputs

  • Target: the Python function or module to fuzz, or the Python C extension to fuzz. Required.
  • Target kind: pure Python, or native C extension. Required; it selects the instrumentation and build path.
  • Expected exceptions: the exception types the target legitimately raises on bad input, so the harness catches them instead of crashing. Optional but recommended.
  • Seed corpus: initial input files for corpus/. Optional; Atheris can start empty.
  • Time/length budget: -max_total_time and -max_len values. Optional; defaults are libFuzzer defaults.
  • Sanitizers: whether AddressSanitizer and/or UndefinedBehaviorSanitizer are enabled. Optional; ASan is the default for native extensions.

Procedure

  1. Determine target kind. If the target is pure Python, follow the pure-Python path. If it is a C extension compiled from source, follow the native-extension path. Do not guess; ask the user when the kind is ambiguous. Done when: the target kind is determined as pure Python or native C extension.

  2. Install Atheris. If the harness directory is not already a uv project (no pyproject.toml present), run uv init --bare once. Then uv add atheris. Verify with python -c "import atheris; print(atheris.__version__)". Done when: Atheris is installed and importable.

  3. Write the harness (fuzz.py or a named file). The harness must be deterministic: no random, time, or other nondeterministic input inside TestOneInput.

    • Decorate the entry point with @atheris.instrument_func.
    • Define TestOneInput(data: bytes). Return early on inputs too short to be meaningful. Call the target. Catch only the expected exception types and pass; let every other exception propagate so the fuzzer records it as a crash.
    • In main(), call atheris.Setup(sys.argv, TestOneInput) then atheris.Fuzz().
    • For structured input, use atheris.FuzzedDataProvider(data) to split one bytes input into typed values (ConsumeUnicodeNoSurrogates, ConsumeBool, ConsumeIntInRange, etc.). Draw in a fixed order; once the buffer runs dry each remaining method returns a zero-value of its type. Do not slice data by hand when the target takes several typed arguments, because every mutation shifts the byte offsets of everything after it. Done when: the harness is written with a deterministic TestOneInput and main().
  4. Instrument pure-Python targets. Wrap imports of the code under test in with atheris.instrument_imports(): so coverage is collected. Do not import the target module after atheris.Setup(). Use atheris.instrument_func for a single function, atheris.instrument_imports() for selected modules, or atheris.instrument_all() only when system-wide instrumentation is intended. Done when: the target is instrumented with the appropriate Atheris mechanism.

  5. Build native C extensions with instrumentation. Before installing the extension from source, export:

    CC=clang
    CXX=clang++
    CFLAGS="-fsanitize=address,fuzzer-no-link"
    CXXFLAGS="-fsanitize=address,fuzzer-no-link"
    LDSHARED="clang -shared"
    LDSHAREDXX="clang++ -shared"
    

    For uv-managed projects, set no-binary = ["<pkg>"] under [tool.uv] in pyproject.toml and run uv sync --reinstall-package <pkg> so the package is built from source; a later uv sync can otherwise silently swap in an uninstrumented wheel. Add undefined to the sanitizer list (-fsanitize=address,undefined,fuzzer-no-link) when UBSan is requested. Done when: the native extension is built from source with sanitizer and fuzzer instrumentation flags.

  6. Configure the native-extension runtime. Set LD_PRELOAD to the Atheris sanitizer shared library:

    export LD_PRELOAD="$(python -c 'import atheris, os; print(os.path.join(os.path.dirname(atheris.__file__), "asan_with_fuzzer.so"))')"
    

    Set ASAN_OPTIONS="allocator_may_return_null=1,detect_leaks=0" to suppress allocation-failure and leak noise. Set ASAN_SYMBOLIZER_PATH to the llvm-symbolizer for the installed clang when stack traces are needed. Done when: LD_PRELOAD and ASAN_OPTIONS are set for the native-extension runtime.

  7. Create the corpus. mkdir corpus and add seed inputs as individual files. Run uv run python fuzz.py corpus/ so libFuzzer loads and grows the corpus. Minimize a merged corpus with uv run python fuzz.py -merge=1 new_corpus/ old_corpus/. Done when: the corpus directory is created and seeded.

  8. Run the campaign. uv run python fuzz.py corpus/ with optional -max_total_time=<seconds>, -max_len=<bytes>, and -workers=N -jobs=N for parallel exploration. Read the output: NEW cov: X means new coverage and corpus growth; ERROR: libFuzzer means a crash was detected and a crash artifact was written. Done when: the campaign runs and produces coverage output or crash artifacts.

  9. Reproduce failures. A crash artifact (named crash-* or leak-*) is written next to the harness. Replay it deterministically with uv run python fuzz.py <artifact> and confirm the same failure recurs. Done when: each saved artifact reproduces the same failure or is classified as nondeterministic.

Failure and recovery

  • No coverage increase. Cause: poor seed corpus or target not instrumented. Recovery: add representative seeds; confirm instrument_imports() wraps the target imports and @atheris.instrument_func wraps the entry point. Do not declare success on a stall.
  • Import errors / modules imported before instrumentation. Recovery: move the target imports inside the atheris.instrument_imports() context manager, before atheris.Setup().
  • Segfault with no ASan output. Cause: LD_PRELOAD not set for a native extension. Recovery: export LD_PRELOAD to asan_with_fuzzer.so and rerun.
  • Build failures for a native extension. Cause: wrong compiler or missing flags. Recovery: verify CC, CXX, CFLAGS, CXXFLAGS, and the clang version; configure no-binary = ["<pkg>"] under [tool.uv] and run uv sync --reinstall-package <pkg>.
  • Memory-allocation or leak noise. Recovery: set ASAN_OPTIONS=allocator_may_return_null=1,detect_leaks=0.
  • Crash artifact does not reproduce. Cause: nondeterminism in the harness (randomness, time, unordered iteration over mutable state). Recovery: remove the nondeterminism so TestOneInput is a pure function of data, then rerun. A non-reproducing crash is not a confirmed defect.
  • Partial-result rule. A campaign that finds no crash is a partial result (coverage gained, no defect proven), not proof of absence. Report coverage and corpus growth; do not claim the target is bug-free.
  • Rollback. Delete the harness file and the corpus/ directory. Restore pyproject.toml and uv.lock to their pre-run state, or if they were created by this skill, remove the added atheris entry and no-binary configuration. The source under test is never modified by this skill.

Output

  • A deterministic, instrumented Atheris harness file.
  • A corpus/ directory of seed and discovered inputs, plus any crash-*/leak-* artifacts.
  • A campaign report: coverage reached, corpus size, executions per second, and for each crash artifact a confirmed reproduction (same failure on replay) or a nondeterminism flag.
  • Terminal classification per crash: confirmed defect (reproduces), nondeterministic (does not reproduce), or no crash found (partial result, not proof of absence).

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

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.

The English summary is being prepared. Showing the original description.

OutlineDriven/odin-claude-plugin37Updated Sep 29, 2026

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.

The English summary is being prepared. Showing the original description.

OutlineDriven/odin-claude-plugin37Updated Sep 29, 2026

af-xdp

Free

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.

The English summary is being prepared. Showing the original description.

OutlineDriven/odin-claude-plugin37Updated Sep 29, 2026

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

The English summary is being prepared. Showing the original description.

OutlineDriven/odin-claude-plugin37Updated Sep 29, 2026

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.

The English summary is being prepared. Showing the original description.

OutlineDriven/odin-claude-plugin37Updated Sep 29, 2026

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.

The English summary is being prepared. Showing the original description.

OutlineDriven/odin-claude-plugin37Updated Sep 29, 2026

See all skills by OutlineDriven

Report a problem with this skill