atheris
Sets up and runs Atheris, the coverage-guided Python fuzzer built on libFuzzer. Covers TestOneInput harnesses, FuzzedDataProvider, instrumenting both pure Python and native C extensions, and running under AddressSanitizer
Install / Use
npx skills add trailofbits/skills --skill atherisInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of atheris
atheris scores 96/100 on our quality scale, 194th of 3,044 Development & Engineering skills we index (top 7%).
Its SKILL.md is 14 KB long, well organised into 57 sections with 24 code examples: a thorough specification that gives an agent plenty to work with.
With 7,225 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated 4 days ago, so atheris is actively maintained.
- It is released under the CC-BY-SA-4.0 license; check its terms before commercial use.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.
Automated pattern scan on 2026-09-28. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
atheris compared with similar skills
All 4 of these similar skills score higher than atheris; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| atheris (this skill)by trailofbits | 96 | 7.2k | 4d ago | SKILL.md |
| Agent-Reachby Panniantong | 100 | 85.8k | 12d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 74.0k | 1d ago | CLAUDE.md |
| ai-job-searchby MadsLorentzen | 100 | 44.2k | today | CLAUDE.md |
| claude-howtoby luongnv89 | 100 | 41.7k | 1d ago | CLAUDE.md |
Frequently asked questions
- How do I install atheris?
- Run
npx skills add trailofbits/skills --skill atheris. The install tabs above show the steps for each supported agent. - Which AI agents does atheris work with?
- It is written for Zed, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is atheris safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It is CC-BY-SA-4.0-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is atheris still maintained?
- The repository was last updated 4 days ago, so atheris is actively maintained.
Skill content
View source on GitHubname: atheris type: fuzzer description: "Sets up and runs Atheris, the coverage-guided Python fuzzer built on libFuzzer. Covers TestOneInput harnesses, FuzzedDataProvider, instrumenting both pure Python and native C extensions, and running under AddressSanitizer. Use when fuzzing a Python package, hunting memory corruption in a Python C extension, or choosing between Atheris and Hypothesis for a Python target."
Atheris
Atheris is a coverage-guided Python fuzzer built on libFuzzer. It enables fuzzing of both pure Python code and Python C extensions with integrated AddressSanitizer support for detecting memory corruption issues.
When to Use
| Fuzzer | Best For | Complexity | |--------|----------|------------| | Atheris | Python code and C extensions | Low-Medium | | Hypothesis | Property-based testing | Low | | python-afl | AFL-style fuzzing | Medium |
Choose Atheris when:
- Fuzzing pure Python code with coverage guidance
- Testing Python C extensions for memory corruption
- Integration with libFuzzer ecosystem is desired
- AddressSanitizer support is needed
Quick Start
import sys
import atheris
@atheris.instrument_func
def TestOneInput(data: bytes):
if len(data) == 4:
if data[0] == 0x46: # "F"
if data[1] == 0x55: # "U"
if data[2] == 0x5A: # "Z"
if data[3] == 0x5A: # "Z"
raise RuntimeError("You caught me")
def main():
atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
if __name__ == "__main__":
main()
Run:
uv run python fuzz.py
Installation
Atheris supports 32-bit and 64-bit Linux, and macOS. We recommend fuzzing on Linux because it's simpler to manage and often faster.
Prerequisites
- Python 3.7 or later
- Recent version of clang (preferably latest release)
- For Docker users: Docker Desktop
Linux/macOS
uv init --bare # once, if the harness directory is not yet a uv project
uv add atheris
Docker Environment (Recommended)
For a fully operational Linux environment with all dependencies configured:
# https://hub.docker.com/_/python
ARG PYTHON_VERSION=3.11
FROM python:$PYTHON_VERSION-slim-bookworm
RUN python --version
RUN apt update && apt install -y \
ca-certificates \
wget \
&& rm -rf /var/lib/apt/lists/*
# LLVM builds version 15-19 for Debian 12 (Bookworm)
# https://apt.llvm.org/bookworm/dists/
ARG LLVM_VERSION=19
RUN echo "deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-$LLVM_VERSION main" > /etc/apt/sources.list.d/llvm.list
RUN echo "deb-src http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-$LLVM_VERSION main" >> /etc/apt/sources.list.d/llvm.list
RUN wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key > /etc/apt/trusted.gpg.d/apt.llvm.org.asc
RUN apt update && apt install -y \
build-essential \
clang-$LLVM_VERSION \
&& rm -rf /var/lib/apt/lists/*
ENV APP_DIR "/app"
RUN mkdir $APP_DIR
WORKDIR $APP_DIR
ENV VIRTUAL_ENV "/opt/venv"
RUN python -m venv $VIRTUAL_ENV
ENV PATH "$VIRTUAL_ENV/bin:$PATH"
# https://github.com/google/atheris/blob/master/native_extension_fuzzing.md#step-1-compiling-your-extension
ENV CC="clang-$LLVM_VERSION"
ENV CFLAGS "-fsanitize=address,fuzzer-no-link"
ENV CXX="clang++-$LLVM_VERSION"
ENV CXXFLAGS "-fsanitize=address,fuzzer-no-link"
ENV LDSHARED="clang-$LLVM_VERSION -shared"
ENV LDSHAREDXX="clang++-$LLVM_VERSION -shared"
ENV ASAN_SYMBOLIZER_PATH="/usr/bin/llvm-symbolizer-$LLVM_VERSION"
# Allow Atheris to find fuzzer sanitizer shared libs
# https://github.com/google/atheris#building-from-source
RUN LIBFUZZER_LIB=$($CC -print-file-name=libclang_rt.fuzzer_no_main-$(uname -m).a) \
python -m pip install --no-binary atheris atheris
# https://github.com/google/atheris/blob/master/native_extension_fuzzing.md#option-a-sanitizerlibfuzzer-preloads
ENV LD_PRELOAD "$VIRTUAL_ENV/lib/python3.11/site-packages/asan_with_fuzzer.so"
# 1. Skip memory allocation failures for now, they are common, and low impact (DoS)
# 2. https://github.com/google/atheris/blob/master/native_extension_fuzzing.md#leak-detection
ENV ASAN_OPTIONS "allocator_may_return_null=1,detect_leaks=0"
CMD ["/bin/bash"]
Build and run:
docker build -t atheris .
docker run -it atheris
Verification
python -c "import atheris; print(atheris.__version__)"
Writing a Harness
Harness Structure for Pure Python
import sys
import atheris
@atheris.instrument_func
def TestOneInput(data: bytes):
"""
Fuzzing entry point. Called with random byte sequences.
Args:
data: Random bytes generated by the fuzzer
"""
# Add input validation if needed
if len(data) < 1:
return
# Call your target function
try:
your_target_function(data)
except ValueError:
# Expected exceptions should be caught
pass
# Let unexpected exceptions crash (that's what we're looking for!)
def main():
atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
if __name__ == "__main__":
main()
Structured Input with FuzzedDataProvider
A target taking several typed arguments wastes most of the fuzzer's inputs if the harness
slices data by hand, because every mutation shifts the byte offsets of everything after it.
atheris.FuzzedDataProvider splits one bytes input into typed values instead:
fdp = atheris.FuzzedDataProvider(data)
name = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 64))
strict = fdp.ConsumeBool()
See structured-input.md for the full method reference, the fixed-draw- order rule, and what each method returns once the buffer runs dry.
Harness Rules
| Do | Don't |
|----|-------|
| Use @atheris.instrument_func for coverage | Forget to instrument target code |
| Catch expected exceptions | Catch all exceptions indiscriminately |
| Use atheris.instrument_imports() for libraries | Import modules after atheris.Setup() |
| Keep harness deterministic | Use randomness or time-based behavior |
See Also: For detailed harness writing techniques, patterns for handling complex inputs, and advanced strategies, see the fuzz-harness-writing technique skill.
Fuzzing Pure Python Code
For fuzzing broader parts of an application or library, use instrumentation functions:
import atheris
with atheris.instrument_imports():
import your_module
from another_module import target_function
def TestOneInput(data: bytes):
target_function(data)
atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
Instrumentation Options:
atheris.instrument_func- Decorator for single function instrumentationatheris.instrument_imports()- Context manager for instrumenting all imported modulesatheris.instrument_all()- Instrument all Python code system-wide
Fuzzing Python C Extensions
Python C extensions require compilation with specific flags for instrumentation and sanitizer support.
Environment Configuration
If using the provided Dockerfile, these are already configured. For local setup:
export CC="clang"
export CFLAGS="-fsanitize=address,fuzzer-no-link"
export CXX="clang++"
export CXXFLAGS="-fsanitize=address,fuzzer-no-link"
export LDSHARED="clang -shared"
Example: Fuzzing cbor2
Install the extension from source:
CBOR2_BUILD_C_EXTENSION=1 uv add --no-binary-package cbor2 'cbor2==5.6.4'
The --no-binary-package flag ensures the C extension is compiled locally with
instrumentation rather than pulled as a prebuilt wheel. Persist that choice with
no-binary-package = ["cbor2"] under [tool.uv] in pyproject.toml, or a later
uv sync can silently swap in an uninstrumented wheel.
Create cbor2-fuzz.py:
import sys
import atheris
# _cbor2 ensures the C library is imported
from _cbor2 import loads
def TestOneInput(data: bytes):
try:
loads(data)
except Exception:
# We're searching for memory corruption, not Python exceptions
pass
def main():
atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
if __name__ == "__main__":
main()
Run:
uv run python cbor2-fuzz.py
Important: When running locally (not in Docker), you must set
LD_PRELOADmanually.
Corpus Management
Creating Initial Corpus
mkdir corpus
# Add seed inputs
echo "test data" > corpus/seed1
echo '{"key": "value"}' > corpus/seed2
Run with corpus:
uv run python fuzz.py corpus/
Corpus Minimization
Atheris inherits corpus minimization from libFuzzer:
uv run python fuzz.py -merge=1 new_corpus/ old_corpus/
See Also: For corpus creation strategies, dictionaries, and seed selection, see the fuzzing-corpus technique skill.
Running Campaigns
Basic Run
uv run python fuzz.py
With Corpus Directory
uv run python fuzz.py corpus/
Common Options
# Run for 10 minutes
uv run python fuzz.py -max_total_time=600
# Limit input size
uv run python fuzz.py -max_len=1024
# Run with multiple workers
uv run python fuzz.py -workers=4 -jobs=4
Interpreting Output
| Output | Meaning |
|--------|---------|
| NEW cov: X | Found new coverage, corpus expanded |
| pulse cov: X | Periodic status update |
| exec/s: X | Executions per second (throughput) |
| corp: X/Yb | Corpus size: X inputs, Y bytes total |
| ERROR: libFuzzer | Crash detected |
Sanitizer Integration
AddressSanitizer (ASan)
AddressSanitizer is automatically integrated when using the provided Docker environment or when compiling with appropriate flags.
For local setup:
export CFLAGS="-fsanitize=address,fuzzer-no-link"
export CXXFLAGS="-fsanitize=address,fuzzer-no-link"
Configure ASan behavior:
export ASAN_OPTIONS="allocator_may_return_null=1,detect_leaks=0"
LD_PRELOAD Configuration
For native extension fuzzing:
export LD_PRELOAD="$(python -c 'import atheris; import os; print(os.path.join(os.path.dirname(atheris.__file__), "asan_with_fuzzer.so"))')"
See Also: For detailed sanitizer configuration, common issues, and advanced flags, see the address-sanitizer and undefined-behavior-sanitizer technique skills.
Common Sanitizer Issues
| Issue | Solution |
|-------|----------|
| LD_PRELOAD not set | Export LD_PRELOAD to point to asan_with_fuzzer.so |
| Memory allocation failures | Set ASAN_OPTIONS=allocator_may_return_null=1 |
| Leak detection noise | Set ASAN_OPTIONS=detect_leaks=0 |
| Missing symbolizer | Set ASAN_SYMBOLIZER_PATH to llvm-symbolizer |
Advanced Usage
Tips and Tricks
| Tip | Why It Helps |
|-----|--------------|
| Use atheris.instrument_imports() early | Ensures all imports are instrumented for coverage |
| Start with small max_len | Faster initial fuzzing, gradually increase |
| Use dictionaries for structured formats | Helps fuzzer understand format tokens |
| Run multiple parallel instances | Better coverage exploration |
Custom Instrumentation
Fine-tune what gets instrumented:
import atheris
# Instrument only specific modules
with atheris.instrument_imports():
import target_module
# Don't instrument test harness code
def TestOneInput(data: bytes):
target_module.parse(data)
Performance Tuning
| Setting | Impact |
|---------|--------|
| -max_len=N | Smaller values = faster execution |
| -workers=N -jobs=N | Parallel fuzzing for faster coverage |
| ASAN_OPTIONS=fast_unwind_on_malloc=0 | Better stack traces, slower execution |
UndefinedBehaviorSanitizer (UBSan)
Add UBSan to catch additional bugs:
export CFLAGS="-fsanitize=address,
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
85.8kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
74.0kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ai-job-search
44.2kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
claude-howto
41.7kA visual, example-driven guide to Claude Code — from basic concepts to advanced agents, with copy-paste templates that bring immediate value.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
