Ruby Advisory Database: a directory of YAML files that bundler-audit reads
A database of vulnerable Ruby Gems
At a glance
- What is it?
- The Ruby Advisory Database is a community effort to compile every security advisory that matters to Ruby libraries, stored as one YAML file per advisory, named after the CVE or GHSA identifier, with the patched version ranges written as Bundler requirements. The format is the product, because a machine has to decide whether a lockfile is safe.
- Who is it for?
- The Ruby Advisory Database fits a Ruby team that wants to know, from the lockfile alone, whether a dependency has a known problem, and it is the input to bundler-audit rather than a tool in itself. It is the wrong choice as a complete answer, because the coverage is whatever volunteers have written down, and because a YAML record can say which versions are patched but cannot say whether your application can reach the vulnerable code.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One file per advisory, named after its identifier
The Ruby Advisory Database is a community effort to compile all the security advisories that are relevant to Ruby libraries, and its physical layout is a plain directory tree.
The top level is a list of directories that match the names of Ruby libraries on rubygems.org, and within each directory there are one or more advisory files for that library, named after the advisory's CVE, GHSA or OSVDB identifier, the last being legacy. The structure looks like this:
gems/:
actionpack/:
CVE-2014-0130.yml CVE-2014-7818.yml CVE-2014-7829.yml CVE-2015-7576.yml
CVE-2015-7581.yml CVE-2016-0751.yml CVE-2016-0752.yml
rubies/:
jruby/:
...
mruby/:
...
ruby/:
...The `gems/` directory contains sub-directories matching the names of the Ruby libraries on rubygems.org, and within each one are the advisory files for that library, named with the CVE or GHSA identifier. The `rubies/` directory contains sub-directories for each Ruby implementation, with advisory files for the interpreter itself, so a vulnerability in Ruby the language is filed next to the interpreter rather than next to a gem.
That split is the first design decision, and it is the right one. A gem advisory and an interpreter advisory have different subjects, different version semantics and different owners, and a consumer of the data has to be able to tell them apart without parsing the file.
The practical benefit of the layout is that it is a Git repository of plain files. A diff shows what changed, a pull request shows what a contributor added, and there is no database server and no schema migration to worry about.
The schema is the contract, and it is strict
Each advisory file contains the advisory information in YAML format, and the README documents a schema in detail. The schema is the interesting part of the project, because it is the part that a machine depends on.
For a gem advisory the required fields are `gem`, the name of the affected gem, `url`, the URL to the full advisory, `title`, the title of the advisory or individual vulnerability, which must be a single line sentence, `date`, the public disclosure date, and `description`, one or more paragraphs describing the vulnerability. Everything else is optional: `library` for the Ruby library the gem belongs to, `framework` for the framework it belongs to, `platform` if the vulnerability is platform-specific, `cve`, `osvdb` and `ghsa` identifiers, `cvss_v2`, `cvss_v3` and `cvss_v4` scores, `unaffected_versions` and `patched_versions` as arrays of version requirements, `related` as a hash of other identifiers and URLs, and `notes` for internal remarks about the vulnerability's inclusion in the database.
The house rules are as detailed as the fields, and they are the kind of detail that only matters once you have tried to keep a few thousand files consistent. The title field is line wrapped at 80. The description uses `description: |` when it is more than one sentence or line, is also wrapped at 80, must not contain ` ` or `%`, and must not include a proof of concept heading in any casing, which is a rule that exists because a proof of concept in a security advisory is a liability rather than an explanation.
The `related` hash has its own convention, since it is a nested structure rather than a flat one: the supported keys are `cve`, `ghsa`, `osvdb` and `url`, the identifier fields are not URLs, and the keys sit four blanks from the left margin.
The `rubies/` schema is shorter and starts with `engine`, which is required and one of `ruby`, `mruby`, `jruby` or `truffleruby`, followed by the same optional identifiers, scores and version fields.
The patched_versions field is the part that has to be right
Of all the fields, the one that matters most to a tool is the version information, and the schema treats it with care.
`patched_versions` is an array of version requirements for the patched versions of the library, and the same array exists as `unaffected_versions` for the versions that are not affected at all. The rule for both is that the version ranges must be quoted, with an example given as `'>= 1.2.3'`, and the rule for `patched_versions` is that it is omitted entirely if you have no patched version identifiers.
That last point is a design statement. A vulnerability with no fix is a normal thing, and a database that requires a patched version for every advisory would either have to invent one or would have to leave a large number of records out. Omitting the field is how the format says that there is no fix, and a consumer can tell the difference between an advisory with a fix and one without.
A trimmed advisory from the repository shows the shape:
---
engine: ruby
cve: 2022-28739
url: https://www.ruby-lang.org/en/news/2022/04/12/buffer-overrun-in-string-to-float-cve-2022-28739/
title: Buffer overrun in String-to-Float conversion
date: 2022-04-12
patched_versions:
- ~> 2.6.10
- ~> 2.7.6
- ~> 3.0.4
- '>= 3.1.2'The values are Bundler version requirements, not versions, and that is the crucial distinction. A gem advisory for a Rails component lists three requirements in the example in the README, `~> 5.2.8`, `~> 6.1.7, >= 6.1.7.1` and `>= 7.0.4.1`, which describe three branches with different fix versions. A consumer evaluates the requirements against the locked version, and the same requirement string that a developer would write in a Gemfile is the one the auditor evaluates. That is why the quoting rule matters: a bare `>= 1.2.3` in YAML is a string anyway, but a value like `> 1.0` would be a YAML boolean comparison artefact, and the format sidesteps the whole class of problem by making the ranges explicit strings.
Where the data comes from, and what is missing
The README is explicit about the data being community contributed, and it lists the sources it expects people to bring.
The project expects others to create the data, such as getting CVEs, GHSAs, OSVDBs, CVSS scores, or original vulnerability information, and there is a document in the repository, `docs/external-data-improvements.md`, with more details on that. The invitation at the top of the README is short: do you know about a vulnerability that is not listed in this database, open an issue or submit a pull request.
So the database is, in a literal sense, a set of files that people have written. That is the strength and the weakness at the same time, and the weakness is specific rather than general. A vulnerability that nobody has noticed is absent, and a vulnerability that nobody has written down is absent in exactly the same way, and the two are indistinguishable from the outside. A lockfile that audits clean tells you that none of the advisories in this repository match your versions, which is a statement about the repository and not about the gems.
The schema reflects that reality in a small way. The `notes` field exists for internal remarks about a vulnerability's inclusion, which is where a maintainer can record why something is in the database or how it was classified, and the `related` field lets an advisory point at the same vulnerability under several identifiers, which is what happens when a vendor publishes a GHSA and the CVE is assigned later.
The `rubies/` tree deserves a separate word, because advisories against the interpreter are a category of their own. A bug in Ruby's own String to Float conversion is filed under `rubies/ruby/` with an `engine` key rather than a `gem` key, and the engine list includes truffleruby, which is the kind of detail that shows the tree is maintained against the implementations people actually run.
How the database is used, and what the tooling around it looks like
The database is not the product, the tool that reads it is. The README names it directly: you can check your own Gemfile.locks against this database by using bundler-audit.
That is the whole interface. A lockfile is a list of exact versions, the database is a list of advisories with version requirements, and a tool that understands both can decide whether a specific locked version falls into an affected range. The data model is small enough that the comparison is the easy part, and the hard part is the coverage and the accuracy of the requirements.
The repository layout reflects that the data is the centre of gravity. `gems/` and `rubies/` hold the records, `lib/` holds whatever the project needs in Ruby, `scripts/` holds the tooling that generates or checks them, `spec/` holds the tests, and `docs/` holds the documentation including the schema reference and the external data improvements guide. There is a `Rakefile` for the tasks, a `Gemfile` for the Ruby side, a `Pipfile` and `Pipfile.lock` for the Python side, which is a sign that some of the tooling around the data is written in Python, and a `.yamllint.yml`, because a database of ten thousand YAML files that all have to parse the same way needs a linter.
There is also a `CONTRIBUTORS.md` and an `AUTHORS`-style record of who wrote what, which matters more here than in most repositories. A record of who contributed a given advisory is a record of who checked that advisory against the upstream source, and that is exactly the provenance a consumer of a security database is entitled to ask about.
Where the advisory database is the wrong tool
The limits are worth naming, because a security database that is treated as a guarantee is worse than no database at all.
The first is coverage, which is the one already described. The database is what volunteers have written down, and a clean audit is a statement about the database rather than about the application.
The second is what the format can express. An advisory record says which versions are affected and which are patched, and that is all. It does not say whether your application calls the vulnerable function, whether the vulnerable path is reachable from user input, or whether a compensating control exists in your stack. Reachability analysis is a different discipline with different data, and this database is not it. A team that needs that has to do it themselves, with a tool that reads the lockfile and the code.
The third is the source of truth. The data is a copy, taken from a CVE record, a GitHub advisory, an OSVDB entry or an original write-up, and a copy ages. A vendor advisory can be revised, a version can be withdrawn, and this repository can only reflect what a contributor noticed. The `related` field and the `notes` field are the places where that staleness is recorded, and they are optional, so a reader has to look for them.
The alternative approach, for a team that wants a single source rather than a copy, is to consume the upstream advisories directly, through the vulnerability databases that the identifiers in these files point at, and to treat this repository as the index that tells you which of your gems have a problem at all. The difference in approach is that this database is a curated, versioned, human-maintained copy that is easy to read and easy to diff, and the upstream is authoritative and harder to consume, and the sensible thing for a team is to use the first to find out where to look and the second to decide what to do.
Editorial conclusion
The Ruby Advisory Database fits a Ruby team that wants to know, from the lockfile alone, whether a dependency has a known problem, and it is the input to bundler-audit rather than a tool in itself. It is the wrong choice as a complete answer, because the coverage is whatever volunteers have written down, and because a YAML record can say which versions are patched but cannot say whether your application can reach the vulnerable code. Before relying on it, run bundler-audit against your lockfile and read the advisories it reports, and treat a clean result as meaning that the known advisories do not cover your dependencies rather than as meaning your dependencies are safe.
Frequently asked questions
How do I check my Ruby gems against known vulnerabilities?
With bundler-audit, which checks your Gemfile.lock against this database. The database itself is the data; the tool is what compares your locked versions against the patched and unaffected version requirements in each advisory.
What format does the Ruby Advisory Database use?
YAML, one file per advisory, named after the CVE, GHSA or legacy OSVDB identifier. The gems/ directory has one sub-directory per gem name, matching rubygems.org, and the rubies/ directory has one sub-directory per Ruby implementation.
Which fields are required in a gem advisory file?
The gem name, the url, the title, which must be a single line sentence, the date of public disclosure, and the description. Optional fields include cve, ghsa, osvdb, cvss_v2, cvss_v3, cvss_v4, unaffected_versions, patched_versions, related and notes, and version ranges in the two version fields must be quoted.
How do I contribute a missing advisory to the Ruby Advisory Database?
Open an issue or submit a pull request. The project expects others to create the data, including CVE records, GHSAs, OSVDB entries, CVSS scores or original vulnerability information, with more detail in docs/external-data-improvements.md in the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rubysec-ruby-advisory-db)Was this useful?