关于 ossfuzz
OSS-Fuzz 是 Google 开发的开源模糊测试项目,为持续测试提供分布式基础设施及本地 CLI。它面向开源项目维护者,也可自行托管以测试私有项目。
主要功能
- 01构建和运行模糊测试 harness
- 02本地执行测试并分析覆盖率
- 03提供构建状态与缺陷跟踪
- 04支持自行托管实例
适用场景
- 01为开源项目设置持续模糊测试
- 02在本地测试现有 harness
- 03复现缺陷报告中的崩溃
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trailofbits/ skills --skill ossfuzz安装后在 Claude Code 中输入/ossfuzz确认已加载。
附带文件agents/openai.yamlassets/trail-of-bits-mark.svg
详细介绍
OSS-Fuzz
OSS-Fuzz 是 Google 开发的开源项目,提供免费的分布式基础设施,用于持续模糊测试。它简化了模糊测试流程,也让修改更加轻松。OSS-Fuzz 只接受部分项目,但其核心是开源的,因此任何人都可以托管自己的实例,用于私有项目。
概览
OSS-Fuzz 提供了一个简单的 CLI 框架,用于构建和启动测试桩,或计算其覆盖率。此外,OSS-Fuzz 还可以作为一项服务,托管根据覆盖率信息等模糊测试输出生成的静态网页。
核心概念
| 概念 | 描述 |
|---|---|
| helper.py | 用于构建镜像、构建模糊测试器以及在本地运行测试桩的 CLI 脚本 |
| Base Images | 提供构建依赖项和编译器的分层 Docker 镜像 |
| project.yaml | 定义 OSS-Fuzz 项目登记所需元数据的配置文件 |
| Dockerfile | 包含项目特定构建依赖项的镜像 |
| build.sh | 为项目构建模糊测试测试桩的脚本 |
| Criticality Score | OSS-Fuzz 团队用于评估项目是否获准加入的指标 |
何时使用
在以下情况下使用此技术:
- 为开源项目设置持续模糊测试
- 需要分布式模糊测试基础设施,但不想管理服务器
- 希望将覆盖率报告和 Bug 跟踪集成到模糊测试中
- 在本地测试现有的 OSS-Fuzz 测试桩
- 复现 OSS-Fuzz Bug 报告中的崩溃
在以下情况下跳过此技术:
- 项目是闭源的(除非托管自己的 OSS-Fuzz 实例)
- 项目未达到 OSS-Fuzz 的关键性分数门槛
- 需要专有或专用的模糊测试基础设施
- 模糊测试简单脚本,不值得为此搭建基础设施
快速参考
| 任务 | 命令 |
|---|---|
| 克隆 OSS-Fuzz | git clone https://github.com/google/oss-fuzz |
| 构建项目镜像 | uv run --no-project python infra/helper.py build_image --pull <project> |
| 使用 ASan 构建模糊测试器 | uv run --no-project python infra/helper.py build_fuzzers --sanitizer=address <project> |
| 运行指定的测试桩 | uv run --no-project python infra/helper.py run_fuzzer <project> <harness> |
| 生成覆盖率报告 | uv run --no-project python infra/helper.py coverage <project> |
| 查看 helper.py 选项 | uv run --no-project python infra/helper.py --help |
OSS-Fuzz 项目组件
OSS-Fuzz 提供多种可公开使用的工具和 Web 界面:
Bug 跟踪器
Bug 跟踪器支持你:
- 查看特定项目的 Bug(最初仅维护者可见,之后改为公开)
- 创建新问题并评论现有问题
- 搜索所有项目中的类似 Bug,以了解相关问题
构建状态系统
构建状态系统可帮助跟踪:
- 所有已纳入项目的构建状态
- 最近一次成功构建的日期
- 构建失败及其持续时间
Fuzz Introspector
- 已加入 OSS-Fuzz 项目的覆盖率数据
- 已覆盖代码的命中频率
- 性能分析和阻塞因素识别
查看此案例研究,了解示例和说明。
分步操作:运行单个测试桩
使用 OSS-Fuzz 不需要托管整个 OSS-Fuzz 平台。通过 helper 脚本即可轻松在本地运行单个测试桩。
第 1 步:克隆 OSS-Fuzz
git clone https://github.com/google/oss-fuzz
cd oss-fuzz
uv run --no-project python infra/helper.py --help
第 2 步:构建项目镜像
uv run --no-project python infra/helper.py build_image --pull <project-name>
这会下载并构建该项目的基础 Docker 镜像。
第 3 步:使用 Sanitizer 构建 Fuzzer
uv run --no-project python infra/helper.py build_fuzzers --sanitizer=address <project-name>
Sanitizer 选项:
--sanitizer=address,用于 AddressSanitizer 和 LeakSanitizer- 也提供其他 Sanitizer(支持情况因语言而异)
**注意:**Fuzzer 构建在 /build/out/<project-name>/ 目录中,其中包含 harness 可执行文件、字典、语料库和崩溃文件。
第 4 步:运行 Fuzzer
uv run --no-project python infra/helper.py run_fuzzer <project-name> <harness-name> [<fuzzer-args>]
如果跳过任何步骤,辅助脚本会自动运行所有遗漏的步骤。
第 5 步:覆盖率分析(可选)
首先,安装 gsutil(跳过 gcloud 初始化)。
uv run --no-project python infra/helper.py build_fuzzers --sanitizer=coverage <project-name>
uv run --no-project python infra/helper.py coverage <project-name>
使用 --no-corpus-download 仅使用本地语料库。该命令会生成覆盖率报告,并在本地托管该报告。
详情请参阅 OSS-Fuzz 官方文档。
常见模式
模式:运行 irssi 示例
**用例:**使用一个简单的已登记项目测试 OSS-Fuzz 设置
# Clone and navigate to OSS-Fuzz
git clone https://github.com/google/oss-fuzz
cd oss-fuzz
# Build and run irssi fuzzer
uv run --no-project python infra/helper.py build_image --pull irssi
uv run --no-project python infra/helper.py build_fuzzers --sanitizer=address irssi
uv run --no-project python infra/helper.py run_fuzzer irssi irssi-fuzz
预期输出:
INFO:__main__:Running: docker run --rm --privileged --shm-size=2g --platform linux/amd64 -i -e FUZZING_ENGINE=libfuzzer -e SANITIZER=address -e RUN_FUZZER_MODE=interactive -e HELPER=True -v /private/tmp/oss-fuzz/build/out/irssi:/out -t gcr.io/oss-fuzz-base/base-runner run_fuzzer irssi-fuzz.
Using seed corpus: irssi-fuzz_seed_corpus.zip
/out/irssi-fuzz -rss_limit_mb=2560 -timeout=25 /tmp/irssi-fuzz_corpus -max_len=2048 < /dev/null
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1531341664
INFO: Loaded 1 modules (95687 inline 8-bit counters): 95687 [0x1096c80, 0x10ae247),
INFO: Loaded 1 PC tables (95687 PCs): 95687 [0x10ae248,0x1223eb8),
INFO: 719 files found in /tmp/irssi-fuzz_corpus
INFO: seed corpus: files: 719 min: 1b max: 170106b total: 367969b rss: 48Mb
#720 INITED cov: 409 ft: 1738 corp: 640/163Kb exec/s: 0 rss: 62Mb
#762 REDUCE cov: 409 ft: 1738 corp: 640/163Kb lim: 2048 exec/s: 0 rss: 63Mb L: 236/2048 MS: 2 ShuffleBytes-EraseBytes-
模式:登记新项目
**用例:**将你的项目添加到 OSS-Fuzz(或私有实例)
在 projects/<your-project>/ 中创建三个文件:
1. project.yaml - 项目元数据:
homepage: "https://github.com/yourorg/yourproject"
language: c++
primary_contact: "[email protected]"
main_repo: "https://github.com/yourorg/yourproject"
fuzzing_engines:
- libfuzzer
sanitizers:
- address
- undefined
2. Dockerfile - 构建依赖项:
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y \
autoconf \
automake \
libtool \
pkg-config
RUN git clone --depth 1 https://github.com/yourorg/yourproject
WORKDIR yourproject
COPY build.sh $SRC/
3. build.sh - 构建 harness:
#!/bin/bash -eu
./autogen.sh
./configure --disable-shared
make -j$(nproc)
# Build harnesses
$CXX $CXXFLAGS -std=c++11 -I. \
$SRC/yourproject/fuzz/harness.cc -o $OUT/harness \
$LIB_FUZZING_ENGINE ./libyourproject.a
# Copy corpus and dictionary if available
cp $SRC/yourproject/fuzz/corpus.zip $OUT/harness_seed_corpus.zip
cp $SRC/yourproject/fuzz/dictionary.dict $OUT/harness.dict
OSS-Fuzz 中的 Docker 镜像
Harness 在 Docker 容器中构建和运行。所有项目共用一个 runner 镜像,但每个项目都有自己的 build 镜像。
镜像层级
镜像按以下顺序逐层构建:
- base_image - 特定版本的 Ubuntu
- base_clang - Clang 编译器;基于
base_image - base_builder - 构建依赖项;基于
base_clang- 特定语言的变体:
base_builder_go等 - 完整列表请参阅 /oss-fuzz/infra/base-images/
- 特定语言的变体:
- 你的项目 Docker 镜像 - 项目专用依赖项;基于
base_builder或语言变体
Runner 镜像(单独使用)
- base_runner - 运行 harness;基于
base_clang - base_runner_debug - 包含调试工具;基于
base_runner
高级用法
提示与技巧
| 提示 | 帮助原因 |
|---|---|
| 不要手动复制源代码 | 项目 Dockerfile 可能已经拉取了最新版本 |
| 查看现有项目 | 浏览 oss-fuzz/projects 获取示例 |
| 将 harness 保存在单独的仓库中 | 例如 curl-fuzzer,组织更清晰 |
| 使用特定版本的编译器 | 基础镜像提供一致的构建环境 |
| 在 Dockerfile 中安装依赖项 | OSS-Fuzz 登记可能需要审批 |
关键性评分
OSS-Fuzz 使用关键性评分评估项目是否获准接纳。请参阅此示例,了解评分方式。
评分较低的项目仍可能被添加到 OSS-Fuzz 私有实例中。
托管你自己的实例
由于 OSS-Fuzz 是开源的,你可以托管自己的实例,用于:
- 不符合公开 OSS-Fuzz 资格的私有项目
- 关键性评分较低的项目
- 定制模糊测试基础设施需求
反模式
| 反模式 | 问题 | 正确做法 |
|---|---|---|
| 在 build.sh 中手动拉取源代码 | 无法使用最新版本 | 让 Dockerfile 处理 git clone |
| 将代码复制到 OSS-Fuzz 仓库 | 难以维护,违反分离原则 | 引用外部 harness 仓库 |
| 忽略基础镜像版本 | 导致构建不一致 | 使用提供的基础镜像和编译器 |
| 跳过本地测试 | 浪费 CI 资源 | 提交 PR 前使用 helper.py 在本地测试 |
| 不检查构建状态 | 构建失败未被发现 | 定期查看构建状态页面 |
特定工具指南
libFuzzer
OSS-Fuzz 主要将 libFuzzer 用作 C/C++ 项目的模糊测试引擎。
Harness 签名:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Your fuzzing logic
return 0;
}
在 build.sh 中构建:
$CXX $CXXFLAGS -std=c++11 -I. \
harness.cc -o $OUT/harness \
$LIB_FUZZING_ENGINE ./libproject.a
集成提示:
- 使用 OSS-Fuzz 提供的
$LIB_FUZZING_ENGINE变量 -fsanitize=fuzzer会自动处理- 尽可能链接静态库
AFL++
OSS-Fuzz 支持将 AFL++ 用作替代模糊测试引擎。
在 project.yaml 中启用:
fuzzing_engines:
- afl
- libfuzzer
集成提示:
- AFL++ harness 可与 libFuzzer harness 协同使用
- 使用持久模式以提升性能
- OSS-Fuzz 会处理特定引擎的编译标志
Atheris(Python)
适用于带有 C 扩展的 Python 项目。
来自 cbor2 集成的示例:
Harness:
import atheris
import sys
import cbor2
@atheris.instrument_func
def TestOneInput(data):
fdp = atheris.FuzzedDataProvider(data)
try:
cbor2.loads(data)
except (cbor2.CBORDecodeError, ValueError):
pass
def main():
atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
if __name__ == "__main__":
main()
在 build.sh 中构建:
# allow-legacy-python: build.sh runs inside the oss-fuzz container, where the shims are absent.
pip3 install .
for fuzzer in $(find $SRC -name 'fuzz_*.py'); do
compile_python_fuzzer $fuzzer
done
集成提示:
- 使用 OSS-Fuzz 提供的
compile_python_fuzzer辅助工具 - 参见博文 持续对 Python C 扩展进行模糊测试
Rust 项目
在 project.yaml 中启用:
language: rust
fuzzing_engines:
- libfuzzer
sanitizers:
- address # Only AddressSanitizer supported for Rust
在 build.sh 中构建:
cargo fuzz build -O --debug-assertions
cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1 $OUT/
集成提示:
- Rust 使用 libfuzzer 时仅支持 AddressSanitizer
- 使用 cargo-fuzz 进行本地开发
- OSS-Fuzz 会处理 Rust 特定的编译
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 构建因缺少依赖项而失败 | Dockerfile 中未包含依赖项 | 在 Dockerfile 中添加 apt-get install 或同等命令 |
| Harness 立即崩溃 | 缺少输入验证 | 在 harness 中添加大小检查 |
| 覆盖率为 0% | Harness 未执行到目标代码 | 确认 harness 确实调用了目标函数 |
| 构建超时 | 构建过程复杂 | 优化 build.sh,并考虑并行构建 |
| 构建时出现 Sanitizer 错误 | 标志不兼容 | 使用 OSS-Fuzz 环境变量提供的标志 |
| 找不到源代码 | Dockerfile 中的工作目录错误 | 设置 WORKDIR 或使用绝对路径 |
相关技能
使用此技术的工具
| 技能 | 应用方式 |
|---|---|
| libfuzzer | OSS-Fuzz 使用的主要模糊测试引擎 |
| aflpp | OSS-Fuzz 支持的替代模糊测试引擎 |
| atheris | 用于在 OSS-Fuzz 中对 Python 项目进行模糊测试 |
| cargo-fuzz | 用于 OSS-Fuzz 中的 Rust 项目 |
相关技术
| 技能 | 关系 |
|---|---|
| coverage-analysis | OSS-Fuzz 通过 helper.py 生成覆盖率报告 |
| address-sanitizer | OSS-Fuzz 项目的默认 Sanitizer |
| fuzz-harness-writing | 将项目纳入 OSS-Fuzz 的必要条件 |
| corpus-management | OSS-Fuzz 会为纳入的项目维护语料库 |
资源
关键外部资源
OSS-Fuzz 官方文档 涵盖 OSS-Fuzz 平台注册、测试框架编写和问题排查的全面文档。
入门指南 逐步介绍如何将新项目注册到 OSS-Fuzz,包括相关要求和审批流程。
cbor2 OSS-Fuzz 集成 PR 将带有 C 扩展的 Python 项目注册到 OSS-Fuzz 的真实案例。内容包括:
- 初始提案和项目介绍
- 关键性评分评估
- 完整实现(project.yaml、Dockerfile、build.sh、测试框架)
Fuzz Introspector 案例研究 介绍使用 Fuzz Introspector 分析覆盖率并识别模糊测试阻碍因素的示例和说明。
视频资源
请查阅 OSS-Fuzz 文档,获取有关项目注册和测试框架开发的研讨会录像及教程。