npx skills add https://github.com/trailofbits/skills --skill ruzzyRuzzy 是一个基于 libFuzzer 构建的、面向 Ruby 的覆盖率引导模糊测试工具。它支持对纯 Ruby 代码和 Ruby C 扩展进行模糊测试,并提供了检测内存损坏和未定义行为的消毒剂支持。
Ruzzy 是目前唯一可用于生产环境的、面向 Ruby 的覆盖率引导模糊测试工具。
在以下情况选择 Ruzzy:
设置环境:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
使用包含的示例进行测试:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby -e 'require "ruzzy"; Ruzzy.dummy'
这应该能快速找到一个崩溃,证明 Ruzzy 工作正常。
Ruzzy 支持 Linux x86-64 和 AArch64/ARM64。对于 macOS 或 Windows,请使用 Dockerfile 或 开发环境。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
使用 clang 编译器标志安装 Ruzzy:
MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
gem install ruzzy
环境变量说明:
MAKE: 覆盖 make 以遵循后续环境变量CC, CXX, LDSHARED, LDSHAREDXX: 确保使用正确的 clang 二进制文件以获得最新功能如果安装失败,启用调试输出:
RUZZY_DEBUG=1 gem install --verbose ruzzy
通过运行示例(参见快速开始部分)来验证安装。
由于 Ruby 解释器的实现细节,纯 Ruby 模糊测试需要两个脚本。
跟踪脚本 (test_tracer.rb):
# frozen_string_literal: true
require 'ruzzy'
Ruzzy.trace('test_harness.rb')
测试套件脚本 (test_harness.rb):
# frozen_string_literal: true
require 'ruzzy'
def fuzzing_target(input)
# 此处放置要模糊测试的代码
if input.length == 4
if input[0] == 'F'
if input[1] == 'U'
if input[2] == 'Z'
if input[3] == 'Z'
raise
end
end
end
end
end
end
test_one_input = lambda do |data|
fuzzing_target(data)
return 0
end
Ruzzy.fuzz(test_one_input)
运行命令:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby test_tracer.rb
C 扩展可以通过单个测试套件文件进行模糊测试,无需跟踪脚本。
msgpack 示例测试套件 (fuzz_msgpack.rb):
# frozen_string_literal: true
require 'msgpack'
require 'ruzzy'
test_one_input = lambda do |data|
begin
MessagePack.unpack(data)
rescue Exception
# 我们寻找的是内存损坏,而非 Ruby 异常
end
return 0
end
Ruzzy.fuzz(test_one_input)
运行命令:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby fuzz_msgpack.rb
| 应做 | 不应做 |
|---|---|
| 如果测试 C 扩展,请捕获 Ruby 异常 | 让 Ruby 异常导致模糊测试器崩溃 |
| 从 test_one_input lambda 返回 0 | 返回其他值 |
| 保持测试套件的确定性 | 使用随机性或基于时间的逻辑 |
| 对纯 Ruby 代码使用跟踪脚本 | 对纯 Ruby 代码跳过跟踪脚本 |
另请参阅: 关于详细的测试套件编写技巧、处理复杂输入的模式以及高级策略,请参阅 fuzz-harness-writing 技术技能。
当为模糊测试安装包含 C 扩展的 Ruby gems 时,请使用消毒剂标志进行编译:
MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
CFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
CXXFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
gem install <gem-name>
| 标志 | 用途 |
|---|---|
-fsanitize=address,fuzzer-no-link | 启用 AddressSanitizer 和模糊测试器插桩 |
-fno-omit-frame-pointer | 提高堆栈跟踪质量 |
-fno-common | 更好地与消毒剂兼容 |
-fPIC | 用于共享库的位置无关代码 |
-g | 包含调试符号 |
在运行任何模糊测试活动之前,设置 ASAN_OPTIONS:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
选项说明:
allocator_may_return_null=1: 跳过常见的低影响分配失败(DoS)detect_leaks=0: Ruby 解释器会泄漏数据,暂时忽略这些use_sigaltstack=0: Ruby 建议在使用 ASan 时禁用 sigaltstackLD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb
注意: LD_PRELOAD 是注入消毒剂所必需的。与 ASAN_OPTIONS 不同,不要导出它,因为它可能会干扰其他程序。
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb /path/to/corpus
所有 libFuzzer 选项都可以作为参数传递:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb /path/to/corpus -max_len=1024 -timeout=10
完整参考请参阅 libFuzzer 选项。
通过传递崩溃文件重新运行崩溃案例:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb ./crash-253420c1158bc6382093d409ce2e9cff5806e980
| 输出 | 含义 |
|---|---|
INFO: Running with entropic power schedule | 模糊测试活动已启动 |
ERROR: AddressSanitizer: heap-use-after-free | 检测到内存损坏 |
SUMMARY: libFuzzer: fuzz target exited | 发生了 Ruby 异常 |
artifact_prefix='./'; Test unit written to ./crash-* | 崩溃输入已保存 |
Base64: ... | 崩溃输入的 Base64 编码 |
Ruzzy 包含一个预编译的 AddressSanitizer 库:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb
使用 ASan 检测:
Ruzzy 也包含 UBSan:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::UBSAN_PATH') \
ruby harness.rb
使用 UBSan 检测:
| 问题 | 解决方案 |
|---|---|
| Ruby 解释器泄漏警告 | 使用 ASAN_OPTIONS=detect_leaks=0 |
| Sigaltstack 冲突 | 使用 ASAN_OPTIONS=use_sigaltstack=0 |
| 分配失败信息过多 | 使用 ASAN_OPTIONS=allocator_may_return_null=1 |
| LD_PRELOAD 干扰工具 | 不要导出它;在 ruby 命令中内联设置 |
另请参阅: 关于详细的消毒剂配置、常见问题和高级标志,请参阅 address-sanitizer 和 undefined-behavior-sanitizer 技术技能。
对 msgpack MessagePack 解析器进行内存损坏的模糊测试。
使用消毒剂安装:
MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
CFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
CXXFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
gem install msgpack
测试套件 (fuzz_msgpack.rb):
# frozen_string_literal: true
require 'msgpack'
require 'ruzzy'
test_one_input = lambda do |data|
begin
MessagePack.unpack(data)
rescue Exception
# 我们寻找的是内存损坏,而非 Ruby 异常
end
return 0
end
Ruzzy.fuzz(test_one_input)
运行:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby fuzz_msgpack.rb
使用自定义解析器对纯 Ruby 代码进行模糊测试。
跟踪脚本 (test_tracer.rb):
# frozen_string_literal: true
require 'ruzzy'
Ruzzy.trace('test_harness.rb')
测试套件 (test_harness.rb):
# frozen_string_literal: true
require 'ruzzy'
require_relative 'my_parser'
test_one_input = lambda do |data|
begin
MyParser.parse(data)
rescue StandardError
# 来自格式错误输入的预期异常
end
return 0
end
Ruzzy.fuzz(test_one_input)
运行:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby test_tracer.rb
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 安装失败 | clang 版本或路径错误 | 验证 clang 路径,使用 clang 14.0.0+ |
cannot open shared object file | LD_PRELOAD 未设置 | 在 ruby 命令中内联设置 LD_PRELOAD |
| 模糊测试器立即退出 | 缺少语料库目录 | 创建语料库目录或将其作为参数传递 |
| 无覆盖率进展 | 纯 Ruby 需要跟踪脚本 | 对纯 Ruby 代码使用跟踪脚本 |
| 泄漏检测信息过多 | Ruby 解释器泄漏 | 设置 ASAN_OPTIONS=detect_leaks=0 |
| 需要安装调试 | 编译错误 | 使用 RUZZY_DEBUG=1 gem install --verbose ruzzy |
| 技能 | 使用场景 |
|---|---|
| fuzz-harness-writing | 编写高效测试套件的详细指导 |
| address-sanitizer | 模糊测试期间的内存错误检测 |
| undefined-behavior-sanitizer | 检测 C 扩展中的未定义行为 |
| libfuzzer | 理解 libFuzzer 选项(Ruzzy 基于 libFuzzer 构建) |
| 技能 | 何时考虑 |
|---|---|
| libfuzzer | 当直接在 C/C++ 中对 Ruby C 扩展代码进行模糊测试时 |
| aflpp | 通过插桩 Ruby 解释器来模糊测试 Ruby 的替代方法 |
介绍 Ruzzy,一个覆盖率引导的 Ruby 模糊测试器 Trail of Bits 官方博客文章,宣布 Ruzzy,涵盖动机、架构和初步结果。
Ruzzy GitHub 仓库 源代码、额外示例和开发说明。
libFuzzer 文档 由于 Ruzzy 基于 libFuzzer 构建,理解 libFuzzer 选项和行为很有价值。
模糊测试 Ruby C 扩展 关于使用编译标志和示例模糊测试 C 扩展的详细指南。
模糊测试纯 Ruby 代码 关于纯 Ruby 模糊测试所需跟踪模式的详细指南。
每周安装量
1.0K
仓库
GitHub 星标数
3.9K
首次出现
Jan 19, 2026
安全审计
安装于
claude-code949
opencode900
gemini-cli885
codex878
cursor861
github-copilot828
Ruzzy is a coverage-guided fuzzer for Ruby built on libFuzzer. It enables fuzzing both pure Ruby code and Ruby C extensions with sanitizer support for detecting memory corruption and undefined behavior.
Ruzzy is currently the only production-ready coverage-guided fuzzer for Ruby.
Choose Ruzzy when:
Set up environment:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
Test with the included toy example:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby -e 'require "ruzzy"; Ruzzy.dummy'
This should quickly find a crash demonstrating that Ruzzy is working correctly.
Ruzzy supports Linux x86-64 and AArch64/ARM64. For macOS or Windows, use the Dockerfile or development environment.
Install Ruzzy with clang compiler flags:
MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
gem install ruzzy
Environment variables explained:
MAKE: Overrides make to respect subsequent environment variablesCC, CXX, LDSHARED, LDSHAREDXX: Ensure proper clang binaries are used for latest featuresIf installation fails, enable debug output:
RUZZY_DEBUG=1 gem install --verbose ruzzy
Verify installation by running the toy example (see Quick Start section).
Pure Ruby fuzzing requires two scripts due to Ruby interpreter implementation details.
Tracer script (test_tracer.rb):
# frozen_string_literal: true
require 'ruzzy'
Ruzzy.trace('test_harness.rb')
Harness script (test_harness.rb):
# frozen_string_literal: true
require 'ruzzy'
def fuzzing_target(input)
# Your code to fuzz here
if input.length == 4
if input[0] == 'F'
if input[1] == 'U'
if input[2] == 'Z'
if input[3] == 'Z'
raise
end
end
end
end
end
end
test_one_input = lambda do |data|
fuzzing_target(data)
return 0
end
Ruzzy.fuzz(test_one_input)
Run with:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby test_tracer.rb
C extensions can be fuzzed with a single harness file, no tracer needed.
Example harness for msgpack (fuzz_msgpack.rb):
# frozen_string_literal: true
require 'msgpack'
require 'ruzzy'
test_one_input = lambda do |data|
begin
MessagePack.unpack(data)
rescue Exception
# We're looking for memory corruption, not Ruby exceptions
end
return 0
end
Ruzzy.fuzz(test_one_input)
Run with:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby fuzz_msgpack.rb
| Do | Don't |
|---|---|
| Catch Ruby exceptions if testing C extensions | Let Ruby exceptions crash the fuzzer |
| Return 0 from test_one_input lambda | Return other values |
| Keep harness deterministic | Use randomness or time-based logic |
| Use tracer script for pure Ruby | Skip tracer for pure Ruby code |
See Also: For detailed harness writing techniques, patterns for handling complex inputs, and advanced strategies, see the fuzz-harness-writing technique skill.
When installing Ruby gems with C extensions for fuzzing, compile with sanitizer flags:
MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
CFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
CXXFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
gem install <gem-name>
| Flag | Purpose |
|---|---|
-fsanitize=address,fuzzer-no-link | Enable AddressSanitizer and fuzzer instrumentation |
-fno-omit-frame-pointer | Improve stack trace quality |
-fno-common | Better compatibility with sanitizers |
-fPIC | Position-independent code for shared libraries |
-g | Include debug symbols |
Before running any fuzzing campaign, set ASAN_OPTIONS:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
Options explained:
allocator_may_return_null=1: Skip common low-impact allocation failures (DoS)detect_leaks=0: Ruby interpreter leaks data, ignore these for nowuse_sigaltstack=0: Ruby recommends disabling sigaltstack with ASanLD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb
Note: LD_PRELOAD is required for sanitizer injection. Unlike ASAN_OPTIONS, do not export it as it may interfere with other programs.
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb /path/to/corpus
All libFuzzer options can be passed as arguments:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb /path/to/corpus -max_len=1024 -timeout=10
See libFuzzer options for full reference.
Re-run a crash case by passing the crash file:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb ./crash-253420c1158bc6382093d409ce2e9cff5806e980
| Output | Meaning |
|---|---|
INFO: Running with entropic power schedule | Fuzzing campaign started |
ERROR: AddressSanitizer: heap-use-after-free | Memory corruption detected |
SUMMARY: libFuzzer: fuzz target exited | Ruby exception occurred |
artifact_prefix='./'; Test unit written to ./crash-* | Crash input saved |
Base64: ... | Base64 encoding of crash input |
Ruzzy includes a pre-compiled AddressSanitizer library:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby harness.rb
Use ASan for detecting:
Ruzzy also includes UBSan:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::UBSAN_PATH') \
ruby harness.rb
Use UBSan for detecting:
| Issue | Solution |
|---|---|
| Ruby interpreter leak warnings | Use ASAN_OPTIONS=detect_leaks=0 |
| Sigaltstack conflicts | Use ASAN_OPTIONS=use_sigaltstack=0 |
| Allocation failure spam | Use ASAN_OPTIONS=allocator_may_return_null=1 |
| LD_PRELOAD interferes with tools | Don't export it; set inline with ruby command |
See Also: For detailed sanitizer configuration, common issues, and advanced flags, see the address-sanitizer and undefined-behavior-sanitizer technique skills.
Fuzzing the msgpack MessagePack parser for memory corruption.
Install with sanitizers:
MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
CFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
CXXFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
gem install msgpack
Harness (fuzz_msgpack.rb):
# frozen_string_literal: true
require 'msgpack'
require 'ruzzy'
test_one_input = lambda do |data|
begin
MessagePack.unpack(data)
rescue Exception
# We're looking for memory corruption, not Ruby exceptions
end
return 0
end
Ruzzy.fuzz(test_one_input)
Run:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby fuzz_msgpack.rb
Fuzzing pure Ruby code with a custom parser.
Tracer (test_tracer.rb):
# frozen_string_literal: true
require 'ruzzy'
Ruzzy.trace('test_harness.rb')
Harness (test_harness.rb):
# frozen_string_literal: true
require 'ruzzy'
require_relative 'my_parser'
test_one_input = lambda do |data|
begin
MyParser.parse(data)
rescue StandardError
# Expected exceptions from malformed input
end
return 0
end
Ruzzy.fuzz(test_one_input)
Run:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby test_tracer.rb
| Problem | Cause | Solution |
|---|---|---|
| Installation fails | Wrong clang version or path | Verify clang path, use clang 14.0.0+ |
cannot open shared object file | LD_PRELOAD not set | Set LD_PRELOAD inline with ruby command |
| Fuzzer immediately exits | Missing corpus directory | Create corpus directory or pass as argument |
| No coverage progress | Pure Ruby needs tracer | Use tracer script for pure Ruby code |
| Leak detection spam | Ruby interpreter leaks | Set ASAN_OPTIONS=detect_leaks=0 |
| Installation debug needed | Compilation errors | Use RUZZY_DEBUG=1 gem install --verbose ruzzy |
| Skill | Use Case |
|---|---|
| fuzz-harness-writing | Detailed guidance on writing effective harnesses |
| address-sanitizer | Memory error detection during fuzzing |
| undefined-behavior-sanitizer | Detecting undefined behavior in C extensions |
| libfuzzer | Understanding libFuzzer options (Ruzzy is built on libFuzzer) |
| Skill | When to Consider |
|---|---|
| libfuzzer | When fuzzing Ruby C extension code directly in C/C++ |
| aflpp | Alternative approach for fuzzing Ruby by instrumenting Ruby interpreter |
Introducing Ruzzy, a coverage-guided Ruby fuzzer Official Trail of Bits blog post announcing Ruzzy, covering motivation, architecture, and initial results.
Ruzzy GitHub Repository Source code, additional examples, and development instructions.
libFuzzer Documentation Since Ruzzy is built on libFuzzer, understanding libFuzzer options and behavior is valuable.
Fuzzing Ruby C extensions Detailed guide on fuzzing C extensions with compilation flags and examples.
Fuzzing pure Ruby code Detailed guide on the tracer pattern required for pure Ruby fuzzing.
Weekly Installs
1.0K
Repository
GitHub Stars
3.9K
First Seen
Jan 19, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code949
opencode900
gemini-cli885
codex878
cursor861
github-copilot828
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
Gemini Interactions API 指南:统一接口、智能体交互与服务器端状态管理
833 周安装
Apollo MCP 服务器:让AI代理通过GraphQL API交互的完整指南
834 周安装
智能体记忆系统构建指南:分块策略、向量存储与检索优化
835 周安装
Scrapling官方网络爬虫框架 - 自适应解析、绕过Cloudflare、Python爬虫库
836 周安装
抽奖赢家选取器 - 随机选择工具,支持CSV、Excel、Google Sheets,公平透明
838 周安装
Medusa 前端开发指南:使用 SDK、React Query 构建电商商店
839 周安装