SKILL·180F8C

atheris

trailofbits
更新于 19 days ago
36 次查看
7,515
642
7,515
在 GitHub 上查看
测试testingdesigndata

关于

This skill sets up Atheris, a coverage-guided Python fuzzer based on libFuzzer, for testing both pure Python code and native C extensions. It covers creating fuzzing harnesses, using FuzzedDataProvider, and integrating AddressSanitizer for memory corruption detection. Use it when you need to fuzz a Python package or hunt for memory bugs in a C extension.

快速安装

Claude Code

推荐
主要方式
npx skills add trailofbits/skills -a claude-code
插件命令备选方式
/plugin add https://github.com/trailofbits/skills
Git 克隆备选方式
git clone https://github.com/trailofbits/skills.git ~/.claude/skills/atheris

在 Claude Code 中复制并粘贴此命令以安装该技能

技能文档

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

FuzzerBest ForComplexity
AtherisPython code and C extensionsLow-Medium
HypothesisProperty-based testingLow
python-aflAFL-style fuzzingMedium

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

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

DoDon't
Use @atheris.instrument_func for coverageForget to instrument target code
Catch expected exceptionsCatch all exceptions indiscriminately
Use atheris.instrument_imports() for librariesImport modules after atheris.Setup()
Keep harness deterministicUse 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 instrumentation
  • atheris.instrument_imports() - Context manager for instrumenting all imported modules
  • atheris.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_PRELOAD manually.

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

OutputMeaning
NEW cov: XFound new coverage, corpus expanded
pulse cov: XPeriodic status update
exec/s: XExecutions per second (throughput)
corp: X/YbCorpus size: X inputs, Y bytes total
ERROR: libFuzzerCrash 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

IssueSolution
LD_PRELOAD not setExport LD_PRELOAD to point to asan_with_fuzzer.so
Memory allocation failuresSet ASAN_OPTIONS=allocator_may_return_null=1
Leak detection noiseSet ASAN_OPTIONS=detect_leaks=0
Missing symbolizerSet ASAN_SYMBOLIZER_PATH to llvm-symbolizer

Advanced Usage

Tips and Tricks

TipWhy It Helps
Use atheris.instrument_imports() earlyEnsures all imports are instrumented for coverage
Start with small max_lenFaster initial fuzzing, gradually increase
Use dictionaries for structured formatsHelps fuzzer understand format tokens
Run multiple parallel instancesBetter 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

SettingImpact
-max_len=NSmaller values = faster execution
-workers=N -jobs=NParallel fuzzing for faster coverage
ASAN_OPTIONS=fast_unwind_on_malloc=0Better stack traces, slower execution

UndefinedBehaviorSanitizer (UBSan)

Add UBSan to catch additional bugs:

export CFLAGS="-fsanitize=address,undefined,fuzzer-no-link"
export CXXFLAGS="-fsanitize=address,undefined,fuzzer-no-link"

Note: Modify flags in Dockerfile if using containerized setup.

Real-World Examples

Two complete harnesses — a pure-Python parser and an HTTP response parser — are in examples.md.

Troubleshooting

ProblemCauseSolution
No coverage increasePoor seed corpus or target not instrumentedAdd better seeds, verify instrument_imports()
Slow executionASan overhead or large inputsReduce max_len, use ASAN_OPTIONS=fast_unwind_on_malloc=1
Import errorsModules imported before instrumentationMove imports inside instrument_imports() context
Segfault without ASan outputMissing LD_PRELOADSet LD_PRELOAD to asan_with_fuzzer.so path
Build failuresWrong compiler or missing flagsVerify CC, CFLAGS, and clang version

Related Skills

Technique Skills

SkillUse Case
fuzz-harness-writingDetailed guidance on writing effective harnesses
address-sanitizerMemory error detection during fuzzing
undefined-behavior-sanitizerCatching undefined behavior in C extensions
coverage-analysisMeasuring and improving code coverage
fuzzing-corpusBuilding and managing seed corpora

Related Fuzzers

SkillWhen to Consider
hypothesisProperty-based testing with type-aware generation
python-aflAFL-style fuzzing for Python when Atheris isn't available

Resources

Key External Resources

Atheris GitHub Repository Official repository with installation instructions, examples, and documentation for fuzzing both pure Python and native extensions.

Native Extension Fuzzing Guide Comprehensive guide covering compilation flags, LD_PRELOAD setup, sanitizer configuration, and troubleshooting for Python C extensions.

Continuously Fuzzing Python C Extensions Trail of Bits blog post covering CI/CD integration, ClusterFuzzLite setup, and real-world examples of fuzzing Python C extensions in continuous integration pipelines.

ClusterFuzzLite Python Integration Guide for integrating Atheris fuzzing into CI/CD pipelines using ClusterFuzzLite for automated continuous fuzzing.

Video Resources

Videos and tutorials are available in the main Atheris documentation and libFuzzer resources.

GitHub 仓库

trailofbits/skills
路径: plugins/testing-handbook-skills/skills/atheris
0
agent-skills
FAQ

常见问题

什么是 atheris Skill?

atheris 是一个 Claude Skill,作者为 trailofbits。Skill 将 Claude 按需加载的说明和资源打包,让 Claude 无需额外提示即可执行与 atheris 相关的任务。

如何安装 atheris?

使用本页的安装命令:将 atheris 作为插件添加到 Claude Code,或将其仓库克隆到 skills 目录,然后重启 Claude 以加载该 Skill。

atheris 属于哪个分类?

atheris 属于测试分类。

atheris 可以免费使用吗?

可以。atheris 已收录在 AIMCP,可免费安装。

相关推荐技能

evaluating-llms-harness
测试

该Skill通过60+个学术基准测试(如MMLU、GSM8K等)评估大语言模型质量,适用于模型对比、学术研究及训练进度追踪。它支持HuggingFace、vLLM和API接口,被EleutherAI等行业领先机构广泛采用。开发者可通过简单命令行快速对模型进行多任务批量评估。

查看技能
cloudflare-cron-triggers
测试

这个Claude Skill提供了关于Cloudflare Cron Triggers的完整知识库,用于通过cron表达式定时执行Workers。它支持配置周期性任务、维护作业和自动化工作流,并能处理常见的cron触发错误。开发者可以用它来设置定时任务、测试cron处理器,并集成Workflows和Green Compute功能。

查看技能
webapp-testing
测试

该Skill为开发者提供了基于Playwright的本地Web应用测试工具集,支持自动化测试前端功能、调试UI行为、捕获屏幕截图和查看浏览器日志。它包含管理服务器生命周期的辅助脚本,可直接作为黑盒工具运行而无需阅读源码。适用于需要快速验证本地Web应用界面和交互功能的开发场景。

查看技能
finishing-a-development-branch
测试

这个Skill用于开发分支完成后的集成决策,当代码实现完成且测试通过时,它会引导开发者选择合适的工作流。它首先验证测试状态,然后提供合并、创建PR或清理等结构化选项。核心价值在于确保代码质量的同时,标准化分支收尾流程。

查看技能