Best for
- Fuzzing Ruby applications or libraries
- Testing Ruby C extensions for memory safety issues
- You need coverage-guided fuzzing for Ruby code
trailofbits/skills/plugins/testing-handbook-skills/skills/ruzzy/SKILL.md
Ruzzy is a coverage-guided Ruby fuzzer by Trail of Bits. Use for fuzzing pure Ruby code and Ruby C extensions.
Decision brief
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.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/trailofbits/skills --skill "plugins/testing-handbook-skills/skills/ruzzy"Inspect the Agent Skill "ruzzy" from https://github.com/trailofbits/skills/blob/65720f8db2ca0c1d1a1805db0dacbabc190a1aa1/plugins/testing-handbook-skills/skills/ruzzy/SKILL.md at commit 65720f8db2ca0c1d1a1805db0dacbabc190a1aa1. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Test with the included toy example:
Verify installation by running the toy example (see Quick Start section).
Before running any fuzzing campaign, set ASANOPTIONS:
Ruzzy is currently the only production-ready coverage-guided fuzzer for Ruby.
Ruzzy supports Linux x86-64 and AArch64/ARM64. For macOS or Windows, use the Dockerfile or development environment.
Permission review
The documentation asks the agent to run terminal commands or scripts.
ruby -e 'require "ruzzy"; Ruzzy.dummy'The documentation asks the agent to run terminal commands or scripts.
MAKE="make --environment-overrides V=1" \The documentation asks the agent to read local files, directories, or repositories.
| `cannot open shared object file` | LD_PRELOAD not set | Set LD_PRELOAD inline with ruby command |The documentation asks the agent to create, modify, or delete local files.
| Fuzzer immediately exits | Missing corpus directory | Create corpus directory or pass as argument |Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 94/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 6,854 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
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.
Frequently asked questions
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.
The source record exposes this install command: npx skills add https://github.com/trailofbits/skills --skill "plugins/testing-handbook-skills/skills/ruzzy". Inspect the command and pinned source before running it.
Static rules flagged exec-script, read-files, write-files in the source; the page lists the matching lines and excerpts.
Alternatives
coreyhaines31/marketingskills
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
garrytan/gbrain
End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.
alirezarezvani/claude-skills
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
dotnet/skills
Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing