Skip to main content

fuzzing-python-expert

Use this skill to fuzz open source Python software projects using Atheris.

소스 정보

저장소
google/oss-fuzz
최근 소스 활동
2026년 6월 12일 10:15
감지된 SKILL.md 언어
영어
스타
12,797
포크
2,953

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
fuzzing-python-expert
description
Use this skill to fuzz open source Python software projects using Atheris.
# Fuzzing Python expert This skill provides the agent with the knowledge and tools to write, build, and validate fuzz targets for Python projects integrated into OSS-Fuzz. Python fuzzing uses [Atheris](https://github.com/google/atheris), which wraps libFuzzer and instruments Python bytecode for coverage-guided fuzzing. ## Fundamental Concepts ### OSS-Fuzz base image Python projects must use the Python base builder image: ```dockerfile FROM gcr.io/oss-fuzz-base/base-builder-python ``` Set `language: python` in `project.yaml`. ### Harness structure A Python fuzz target is a `.py` file (named `fuzz_<target>.py` by convention) that follows this pattern: ```python #!/usr/bin/python3 import sys import atheris # Import the module under test after atheris.instrument_imports() or within # the atheris.instrument_all() context so bytecode is instrumented. def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) # Extract typed values from the raw fuzzer bytes. value = fdp.ConsumeString(128) try: my_module.parse(value) except (ValueError, TypeError, KeyError): # Expected exceptions from invalid input are not bugs. pass def main(): atheris.instrument_all() # instrument all loaded Python modules atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ``` ### Instrumenting imports selectively When `instrument_all()` is too broad (e.g. causes conflicts with C extensions), instrument specific modules using the `instrument_imports()` context manager: ```python import atheris with atheris.instrument_imports(): import my_module import my_module.subpackage ``` ### FuzzedDataProvider reference `atheris.FuzzedDataProvider` splits the raw byte stream into typed values: | Method | Description | |---|---| | `ConsumeBytes(count)` | `bytes` of length count | | `ConsumeByteList(count)` | `list[int]` of length count | | `ConsumeString(count)` | decoded `str` (may contain surrogates) | | `ConsumeUnicode(count)` | `str` without surrogates | | `ConsumeUnicodeNoSurrogates(count)` | strict `str` | | `ConsumeInt(nbytes)` | signed int from nbytes | | `ConsumeIntInRange(min, max)` | int in range | | `ConsumeFloat()` | float | | `ConsumeBool()` | bool | | `ConsumeIntList(count, nbytes)` | list of ints | | `PickValueInList(lst)` | random element | | `ConsumeRemainingBytes()` | all remaining bytes | ### Building in OSS-Fuzz `build.sh` installs the target package and uses the `compile_python_fuzzer` helper to turn each `fuzz_*.py` file into a standalone fuzzer binary in `$OUT`: ```bash # build.sh # Install the package under test. pip3 install . # Compile all fuzz targets found in $SRC. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer "$fuzzer" done ``` `compile_python_fuzzer` handles linking against Atheris and libFuzzer and produces an executable in `$OUT` named after the `.py` file. ### Seed corpus and dictionaries - Place seed files in `$OUT/<fuzzer_name>_seed_corpus/` or zip them as `$OUT/<fuzzer_name>_seed_corpus.zip`. - Dictionaries go to `$OUT/<fuzzer_name>.dict` — especially valuable for text-format parsers (JSON, XML, YAML, CSV, etc.). - For targets that parse a structured format, generating seeds with a script beats hand-picking a few files — random mutation rarely passes the parser's early checks. See the [structured seed generation reference](../oss-fuzz-engineer/references/structured_seed_generation.md). ## Characteristics of good Python fuzzing harnesses 1. **Instruments the right modules**: use `instrument_all()` for simplicity or `instrument_imports()` for targeted instrumentation. Without instrumentation coverage guidance is blind. 2. **Targets attack surface**: parsers, template engines, serialisation (pickle, JSON, YAML, XML), network protocol handling, and any API that accepts untrusted strings or bytes. 3. **Catches expected exceptions**: wrap target calls in `try/except` for the documented exception types the target raises on bad input. Only unexpected exceptions and hard crashes are findings. 4. **Uses `FuzzedDataProvider` for structured input** rather than feeding raw bytes directly to APIs that expect text — most Python APIs work on strings, not bytes. 5. **Avoids importing under test inside `TestOneInput`**: imports should happen at module level (inside the `instrument_imports()` block if used) so they are instrumented and not re-executed per iteration. 6. **Is fast**: avoid file I/O, network calls, or subprocess invocations inside `TestOneInput`. 7. **Avoids non-determinism**: no `random`, no `datetime.now()`, no `os.urandom()` inside the fuzz function. 8. **Enables Python coverage**: pass `enable_python_coverage=True` to `atheris.Setup` for bytecode-level coverage tracking. ## What Python fuzzing finds Python is memory-safe, so the focus is on: - **Unhandled exceptions**: `ValueError`, `RecursionError`, `MemoryError`, `UnicodeDecodeError`, and any exception the library should have caught and converted to a clean error. - **`AssertionError`**: internal invariant violations triggered by crafted input. - **Hangs / infinite loops**: detected by OSS-Fuzz's timeout. - **Crashes in C extensions**: Python libraries that wrap C code (e.g. lxml, Pillow, cryptography) can still have memory-corruption bugs in their C layer, which Atheris will surface because libFuzzer runs the whole process. - **Logic errors**: incorrect output, silent data corruption, wrong parsing results on edge-case inputs. ## Operational guidelines - Always validate with: ``` python3 infra/helper.py build_fuzzers <project> python3 infra/helper.py check_build <project> python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30 ``` - An instant crash usually means an exception is being raised on every input. Run the harness locally (`python3 fuzz_target.py`) on a sample input to debug before building through OSS-Fuzz. - Test the harness locally before the OSS-Fuzz build: ```python python3 fuzz_target.py <seed_file> ``` Atheris supports running in single-input mode outside libFuzzer. - Install the package locally (`pip3 install .`) and iterate quickly before going through the Docker build. - When iterating locally clone the upstream repo and switch the Dockerfile from `RUN git clone` to `COPY` to avoid network round-trips. - Document why each entry point was chosen and what class of bugs it may find.
GitHub에서 보기