rubysec/bundler-audit
Patch-level verification for Bundler
Slowing — last commit 5mo ago
worst of 4 axescopyleft license (GPL-3.0) — review compatibility
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 5mo ago
- ✓10 active contributors
- ✓GPL-3.0 licensed
Show 5 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Slowing — last commit 5mo ago
- ⚠Concentrated ownership — top contributor handles 67% of recent commits
- ⚠GPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/rubysec/bundler-audit)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/rubysec/bundler-audit on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: rubysec/bundler-audit
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/rubysec/bundler-audit shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Slowing — last commit 5mo ago
- Last commit 5mo ago
- 10 active contributors
- GPL-3.0 licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 5mo ago
- ⚠ Concentrated ownership — top contributor handles 67% of recent commits
- ⚠ GPL-3.0 is copyleft — check downstream compatibility
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live rubysec/bundler-audit
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/rubysec/bundler-audit.
What it runs against: a local clone of rubysec/bundler-audit — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in rubysec/bundler-audit | Confirms the artifact applies here, not a fork |
| 2 | License is still GPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 187 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of rubysec/bundler-audit. If you don't
# have one yet, run these first:
#
# git clone https://github.com/rubysec/bundler-audit.git
# cd bundler-audit
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of rubysec/bundler-audit and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "rubysec/bundler-audit(\\.git)?\\b" \\
&& ok "origin remote is rubysec/bundler-audit" \\
|| miss "origin remote is not rubysec/bundler-audit (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is GPL-3.0" \\
|| miss "license drift — was GPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "lib/bundler/audit.rb" \\
&& ok "lib/bundler/audit.rb" \\
|| miss "missing critical file: lib/bundler/audit.rb"
test -f "lib/bundler/audit/scanner.rb" \\
&& ok "lib/bundler/audit/scanner.rb" \\
|| miss "missing critical file: lib/bundler/audit/scanner.rb"
test -f "lib/bundler/audit/database.rb" \\
&& ok "lib/bundler/audit/database.rb" \\
|| miss "missing critical file: lib/bundler/audit/database.rb"
test -f "lib/bundler/audit/cli.rb" \\
&& ok "lib/bundler/audit/cli.rb" \\
|| miss "missing critical file: lib/bundler/audit/cli.rb"
test -f "lib/bundler/audit/advisory.rb" \\
&& ok "lib/bundler/audit/advisory.rb" \\
|| miss "missing critical file: lib/bundler/audit/advisory.rb"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 187 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~157d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/rubysec/bundler-audit"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
bundler-audit is a Ruby security scanner that performs patch-level vulnerability verification against your Gemfile.lock dependencies. It compares gem versions in your lock file against a curated database of known security advisories (from ruby-advisory-db), detecting unpatched vulnerable gems and insecure package sources (http:// and git:// URIs). It outputs findings in multiple formats (text, JSON, JUnit) and integrates with Bundler via a CLI and Rake task. Modular CLI-driven architecture: lib/bundler/audit/cli.rb (Thor-based command handler) parses user input, lib/bundler/audit/scanner.rb analyzes the Gemfile.lock against advisories, lib/bundler/audit/database.rb manages the advisory database, and lib/bundler/audit/report.rb + lib/bundler/audit/results/ package findings. Format plugins (JSON, JUnit, text) in lib/bundler/audit/cli/formats/ handle output serialization.
👥Who it's for
Ruby developers and DevOps engineers who need to audit their application's gem dependencies for known security vulnerabilities as part of CI/CD pipelines, pre-commit hooks, or manual security reviews. Teams using Bundler for dependency management who want shift-left security without external SaaS scanning services.
🌱Maturity & risk
Actively maintained production-ready tool with CI/CD via GitHub Actions (ruby.yml workflow), Code Climate integration, and proper test coverage. The codebase shows consistent updates and is widely used in Ruby ecosystems. Gem version badge indicates it's published and versioned on RubyGems.
Low risk: small focused Ruby codebase (~133KB) with clear scope, no external API dependencies (uses local advisory database), and established test structure. Main dependency risk is on ruby-advisory-db accuracy and update frequency, but this is maintained by the same organization (rubysec). Single-maintainer risk exists but project is stable and read-mostly after initial setup.
Active areas of work
Active maintenance with GitHub Actions CI for Ruby version matrix testing. The repository appears to focus on stability and compatibility rather than major feature development. Recent work likely involves Ruby version compatibility (see .github/workflows/ruby.yml) and output format improvements (formats/ directory structure).
🚀Get running
git clone https://github.com/rubysec/bundler-audit && cd bundler-audit && bundle install && rake test (or bundle exec rspec spec/) to run tests. Then bundle-audit can be invoked as a gem or via bin/bundle-audit on a target project's Gemfile.lock.
Daily commands: Development: bundle exec rake test or bundle exec rspec. CLI usage: bundle exec bundler-audit (in a project with Gemfile.lock) or bundle-audit with no arguments. Use bundle-audit update to refresh the advisory database. Integrations: Rake task via require 'bundler/audit/task' in Rakefile, or CI/CD via github/actions or standard gem installation.
🗺️Map of the codebase
lib/bundler/audit.rb— Main entry point and public API for the audit library; orchestrates the core vulnerability checking workflow.lib/bundler/audit/scanner.rb— Core scanning engine that parses Gemfile.lock, compares against advisory database, and detects vulnerabilities and insecure sources.lib/bundler/audit/database.rb— Manages advisory database loading and querying; critical for vulnerability detection to work correctly.lib/bundler/audit/cli.rb— Command-line interface using Thor; entry point for the bundle-audit executable and all user interactions.lib/bundler/audit/advisory.rb— Advisory data structure representing a single security vulnerability with metadata, version ranges, and remediation info.lib/bundler/audit/report.rb— Aggregates scanner results and generates audit reports with configurable filtering and output formatting.lib/bundler/audit/configuration.rb— Loads and validates .bundler-audit.yml config files; enables users to ignore known advisories or override defaults.
🧩Components & responsibilities
- Scanner (Ruby, Bundler, Gem::Requirement) — Parses Gemfile.lock, loads all advisories, performs version matching, detects insecure sources, returns raw result objects
- Failure mode: Missing or incorrect version matches; undetected insecure sources; fails if Gemfile.lock malformed or advisories unreachable
- Advisory Database (YAML, File I/O or git clone) — Loads advisory YAML files from gem or git, parses into Advisory objects, provides queryable index by gem name
- Failure mode: Stale advisories if not updated; corrupt YAML causes parse errors; missing advisories lead to false negatives
- Report Generator (Ruby, YAML config parsing) — Filters scanner results using ignores from .bundler-audit.yml configuration, aggregates into final report, tracks counts
- Failure mode: Invalid config prevents report generation; incorrect ignore logic allows vulnerable gems to be hidden
- CLI / Thor (Thor, File I/O) — Routes subcommands (check, download, generate), parses options, invokes scanner/report, selects formatter, returns exit code
- Failure mode: Incorrect exit codes break CI/CD pipelines; parsing errors prevent command execution
- Output Formatters (String interpolation, JSON serialization, XML generation) — Render report to text, JSON, JUnit, or custom formats for human or tool consumption
- Failure mode: Malformed JSON breaks parsers; missing fields in output prevent tooling integration
🔀Data flow
Gemfile.lock→Scanner— Scanner parses locked gem names and versionsAdvisory Database→Scanner— Scanner queries database for each gem; matches if version in vulnerable range- `` →
undefined— undefined
🛠️How to make changes
Add a new output format
- Create a new format class inheriting from a base format in lib/bundler/audit/cli/formats/ (
lib/bundler/audit/cli/formats/your_format.rb) - Implement render(report) method to produce your format (
lib/bundler/audit/cli/formats/your_format.rb) - Register your format in the formats factory (
lib/bundler/audit/cli/formats.rb) - Add tests following the pattern of other format specs (
spec/cli/formats/your_format_spec.rb)
Support a new result type (new vulnerability class)
- Create result class inheriting from Result base class (
lib/bundler/audit/results/your_result_type.rb) - Add detection logic to scanner to populate your result type (
lib/bundler/audit/scanner.rb) - Update all format renderers to handle your result type (
lib/bundler/audit/cli/formats/text.rb)
Extend the advisory database format
- Modify advisory YAML parsing and validation (
lib/bundler/audit/advisory.rb) - Update the database loader to handle new advisory fields (
lib/bundler/audit/database.rb) - Add fixtures with new format for tests (
spec/fixtures/advisory/CVE-2020-1234.yml)
🔧Why these technologies
- Ruby + Bundler — Auditing Bundler's Gemfile.lock requires deep integration with Ruby's dependency manager; native Ruby implementation allows direct inspection of gem specs.
- Thor CLI framework — Provides structured command routing, option parsing, and help text generation without external dependencies beyond what Bundler already requires.
- YAML advisory database — Human-readable, version-controllable format for security advisories that can be distributed via gem or git repository; decouples from network calls.
- Semantic versioning matching — Gems follow semver in Bundler; advisory database specifies vulnerable version ranges; matching logic can determine if locked gem is affected.
⚖️Trade-offs already made
-
Offline-by-default with optional database updates
- Why: Security should not depend on external network availability; users can audit locally without connectivity.
- Consequence: Database must be manually updated or bundled; older installations may check against stale advisories.
-
Configuration via .bundler-audit.yml for ignoring advisories
- Why: Allows teams to accept risk and document known workarounds without modifying code.
- Consequence: Developers must commit ignore decisions to version control; requires discipline to not ignore critical advisories.
-
Multiple output formats (text, JSON, JUnit) via pluggable system
- Why: Text for humans, JSON for tooling, JUnit for CI integration; single codebase can serve multiple audiences.
- Consequence: Each new format requires updates to formatters; output consistency is manual responsibility.
🚫Non-goals (don't propose these)
- Does not perform runtime introspection; only static analysis of Gemfile.lock
- Does not suggest patches or automatically update gems
- Does not authenticate to private gem repositories
- Does not monitor dependencies over time or track vulnerability lifecycles
- Does not provide remediation guidance beyond version ranges
- Does not support license compliance checking (only security vulnerabilities)
- Not a replacement for Dependabot or professional security scanning
🪤Traps & gotchas
Advisory database (ruby-advisory-db) is cloned to ~/.bundler-audit/ by default — ensure user has write permissions and network access for 'bundle-audit update'. Gemfile.lock must exist in the target directory. Gem version comparisons use Gem::Requirement parsing, which can behave unexpectedly with pre-release versions (1.0.0.pre). CI workflows test against multiple Ruby versions — local development must match one of those (see .github/workflows/ruby.yml matrix). Configuration file .bundler-audit.yml uses YAML format and path is relative to working directory.
🏗️Architecture
💡Concepts to learn
- Semantic Versioning (SemVer) & Gem::Requirement — bundler-audit uses Gem::Requirement to parse and match version constraints (e.g., '~> 3.2.13') against installed versions; understanding SemVer is critical for understanding why certain gems are flagged as vulnerable or patched
- Vulnerability Advisories & CVE/CWE Classification — Each advisory in ruby-advisory-db contains severity, CWE/CVE identifiers, and affected version ranges; you need to understand advisory structure to modify scanner logic or database interactions
- Thor Framework (CLI DSL) — bundler-audit uses Thor for CLI command parsing and subcommand dispatch; understanding Thor's task definitions and option parsing is essential for adding or modifying commands
- Strategy Pattern (Output Formatters) — The formats/ plugin system uses the strategy pattern to swap between JSON, JUnit, and text output; extending this requires understanding how formatters implement a common interface
- Lock File Format & Bundler.load_gemfile_lock — Scanner.rb parses Gemfile.lock using Bundler internals to extract gem names and pinned versions; understanding the lock file structure is needed to modify dependency analysis
- Insecure Protocol Detection (http:// and git://) — bundler-audit flags sources using unencrypted http or git protocols as security risks; this is a secondary audit layer beyond version vulnerability checking
- Configuration File Merging & YAML Parsing — Configuration.rb loads .bundler-audit.yml to allow users to ignore specific advisories; understanding how configuration overrides detection results is important for feature requests or bug fixes
🔗Related repos
rubysec/ruby-advisory-db— The authoritative source of vulnerability data that bundler-audit consumes; database updates and advisory format changes happen hereaquasecurity/trivy— Modern vulnerability scanner supporting Ruby/Bundler with a broader language ecosystem; represents an alternative approach with centralized scanning vs. bundler-audit's local-first designjeremylong/DependencyCheck— Enterprise-grade multi-language dependency checker that includes Ruby support; similar use case but more heavyweight and organization-focusedrubysec/bundler-audit-action— GitHub Action wrapper around bundler-audit for seamless CI/CD integration; shows how the tool is consumed in modern workflowsbundler/bundler— Parent Ruby dependency manager that bundler-audit extends with security auditing capabilities; uses Bundler APIs for lock file parsing
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive integration tests for CLI output formats
The repo has JSON, JUnit, and Text formatters in lib/bundler/audit/cli/formats/ with corresponding specs, but the test coverage gaps are evident. spec/cli/formats/ is missing dedicated test files for edge cases like malformed advisories, empty results, and format-specific error handling. This would improve reliability of the audit output across different CI/CD integrations.
- [ ] Review existing tests in spec/cli/formats/json_spec.rb, junit_spec.rb, and text_spec.rb
- [ ] Add test cases for each formatter with empty vulnerability lists
- [ ] Add test cases for each formatter with mixed severity levels
- [ ] Add test cases for each formatter with special characters and encoding edge cases
- [ ] Verify spec/cli/formats_spec.rb covers all format selection paths
Add tests for configuration file parsing with invalid YAML and edge cases
The repo supports .bundler-audit.yml configuration (shown in spec/bundle/unpatched_gems_with_dot_configuration/), but spec/configuration_spec.rb likely lacks coverage for malformed YAML, missing required fields, and path resolution edge cases. This is critical since configuration drives the vulnerability ignore logic.
- [ ] Review spec/configuration_spec.rb for existing test coverage
- [ ] Add tests for invalid YAML syntax in .bundler-audit.yml files
- [ ] Add tests for missing 'ignore' key and other required fields
- [ ] Add tests for relative vs absolute paths in ignore configurations
- [ ] Add tests for configuration file precedence (current directory vs parent directories)
Add vulnerability update mechanism tests and database sync tests
The lib/bundler/audit/database.rb handles vulnerability data sourcing, but spec/database_spec.rb may lack tests for the advisory database update workflow, network failures, and corrupted advisory files. The spec/fixtures/advisory/ directory shows test data exists (CVE-2020-1234.yml, not_a_hash.yml), suggesting edge cases need formalized testing.
- [ ] Review spec/database_spec.rb current test coverage
- [ ] Add tests for database update with network unavailable
- [ ] Add tests for parsing malformed advisory YAML (see spec/fixtures/advisory/not_a_hash.yml)
- [ ] Add tests for handling missing advisory metadata fields
- [ ] Add tests for advisory caching and freshness verification logic
🌿Good first issues
- Add missing test coverage for lib/bundler/audit/cli/thor_ext/shell/basic/say_error.rb — this custom error output extension has no corresponding test file in spec/, making it a good place to write shell output integration tests.
- Implement CSV output format in lib/bundler/audit/cli/formats/ following the existing JSON and JUnit patterns — useful for CI/CD integration and appears to be a missing output option despite multiple format plugins already existing.
- Add YAML serialization option to lib/bundler/audit/cli/formats/ to complement JSON/JUnit — many Ruby projects prefer YAML config, and the pattern is well-established in adjacent formatters, making this a low-risk feature addition.
⭐Top contributors
Click to expand
Top contributors
- @postmodern — 67 commits
- @dependabot[bot] — 21 commits
- @petergoldstein — 3 commits
- @misdoro — 2 commits
- @andriusm — 2 commits
📝Recent commits
Click to expand
Recent commits
f8b06eb— Updated the ChangeLog for 0.9.3. (postmodern)e4fb10a— Version bump to 0.9.3. (postmodern)34cd522— Added Ruby 4.0 to the CI matrix. (postmodern)22da9d7— Added Ruby 3.5 to the CI matrix. (postmodern)0c2afaf— Require rubygems-tasks ~> 0.3 for Ruby 3.5 and 4.0. (postmodern)309d203— Allow using bundler 4.x (byroot)d40dc75— Remove syntax highlighting from example output. (postmodern)91a912f— Be consistent and only use markdown code fences. (postmodern)fc1bc0a— Fixed typo in@returntag. (postmodern)276e065— Update RubyGems in GitHub Actions CI (#406) (yahonda)
🔒Security observations
bundler-audit is a security scanning tool with generally good security practices. The primary concerns are YAML deserialization risks (potentially critical if untrusted advisories are loaded) and insufficient input validation in CLI handling. The tool's purpose is to improve supply chain security, but it should follow defense-in-depth principles. Recommend immediate mitigation of YAML loading and CLI input validation vulnerabilities. The test fixtures are appropriate and isolated from production code.
- Medium · Potential YAML Deserialization Risk —
lib/bundler/audit/configuration.rb, lib/bundler/audit/advisory.rb, spec/fixtures/advisory/. The codebase loads YAML configuration files (.bundler-audit.yml) and advisory files without explicit safe loading. YAML.load() can deserialize arbitrary Ruby objects, potentially leading to code execution if advisory data or user configs are untrusted. Fix: Use YAML.safe_load() instead of YAML.load() for all configuration and advisory file parsing. Ensure all YAML operations specify permitted_classes and aliases parameters. - Medium · Command Injection via CLI Arguments —
lib/bundler/audit/cli.rb, lib/bundler/audit/database.rb. The CLI module (lib/bundler/audit/cli.rb) processes user input for file paths and database URLs. Insufficient input validation could allow command injection if these values are passed to shell commands. Fix: Validate and sanitize all file paths and URLs. Use file system APIs directly instead of shell commands. Avoid passing user input to system() or backticks. - Low · Insecure Source Detection —
lib/bundler/audit/results/insecure_source.rb, lib/bundler/audit/scanner.rb. The tool checks for insecure gem sources (http:// and git://), which is good. However, the detection mechanism should also flag sources without certificate pinning or authentication. Fix: Enhance insecure source detection to warn about sources without HTTPS/SSH, missing authentication, or untrusted certificates. - Low · Hardcoded Test Credentials —
spec/fixtures/, spec/bundle/. Test fixtures and specs may contain example data that resembles credentials or sensitive information that should not be in source code. Fix: Audit test fixtures for any credential-like strings. Use environment variables or secret management for test data. - Low · Missing Input Validation on Advisory Data —
lib/bundler/audit/advisory.rb, spec/fixtures/advisory/. Advisory YAML files (CVE-2020-1234.yml, not_a_hash.yml) are loaded without strict schema validation. Malformed or malicious advisory data could cause unexpected behavior. Fix: Implement strict schema validation for advisory YAML files. Validate required fields (gem, cve, advisory, severity, etc.) and enforce type constraints.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.