OSV records are not equally complete. In five ecosystem exports fetched on 19 October 2026, the share of records with a summary ranged from 83.6 to 100 percent, aliases from 54.7 to 97.8 percent, and credits from 0.7 to 78.6 percent. Check field completeness before you compare ecosystems.
What was measured
The author downloaded the per-ecosystem all.zip files from the OSV bucket, which OSV documents as containing that ecosystem's vulnerabilities, including withdrawn records. Each record is one JSON file. For each of five ecosystems, the author counted records that had a non-empty value for each optional field. The schema marks summary, aliases and credits as optional, so absence is legal, not an error.
| Ecosystem | Records | Summary | Aliases | Credits | Withdrawn |
|---|---|---|---|---|---|
| PyPI | 26,383 | 83.6% | 54.7% | 44.9% | 2.3% |
| crates.io | 2,944 | 100.0% | 76.7% | 0.7% | 4.2% |
| Go | 9,661 | 99.8% | 97.8% | 5.2% | 1.8% |
| RubyGems | 5,464 | 100.0% | 83.8% | 78.6% | 1.3% |
| Packagist | 7,303 | 90.0% | 86.5% | 9.3% | 2.1% |
Percentages are of records in the export, rounded to one decimal.
What to take from it
Summary. Every record in these exports had details text, but not every one had a one line summary. In PyPI, 4,316 records had details but no summary. If you build a table of advisory titles, you need a fallback.
Aliases. These link a record to the same flaw in other databases. A record with no alias is not invalid; it may be a vulnerability that has no CVE. When you count unique vulnerabilities by merging aliases, records without aliases stay as singletons. See aliases, upstream and related.
Credits. These vary by an order of magnitude and mostly reflect how each source records reporters. Do not read a low credit share as a statement about community engagement.
Withdrawn. The schema says that if the withdrawn field is missing, the entry has not been withdrawn. Exports include withdrawn records, so exclude them from "current advisory" counts and say so.
Method notes you should copy
- Name the files and fetch date. The export's last modified time differed by ecosystem, from 17 to 19 October 2026.
- Define "present" as a non-empty value.
- Report the withdrawn count separately.
- Do not pool ecosystems into one percentage unless you also give the per-ecosystem table.
The pooled number would be dominated by the largest ecosystem, which hides the differences above.
What this does not show
Five ecosystems are a sample of the whole OSV database, not the whole. Completeness of a field says nothing about the accuracy of what it contains. And these shares will change as sources edit records.
A worked example with PyPI
Take PyPI, the largest export in the sample at 26,383 records. Of those, 22,067 had a summary (83.6 percent) and 4,316 had details but no summary, a gap of 16.4 percent. If you were building a table of advisory titles, a naive script that prints the summary would show blanks for those 4,316 records. A fallback to the first line of details solves it, and you should say you did that.
For aliases, 14,438 PyPI records had at least one, which leaves 11,945 without. A record with no alias cannot be linked to a CVE by that field. If your analysis counts unique vulnerabilities by merging aliases, those records each count as one, and your unique count will be higher than if they had CVE aliases. This is why a pooled count of advisories and a count of unique flaws can differ.
Ranges and versions
Records describe affected versions in two ways: ranges and explicit version lists. In the sample, Go records almost always had ranges (9,649 of 9,661) while RubyGems records mostly had version lists (5,450 of 5,464) and only 1,192 had ranges. A script that reads only ranges will miss most RubyGems detail. This is not an error in either source, just a difference in how each records the data, and it is the kind of difference that OSV version ranges explained covers in depth.
| Field | Why it varies |
|---|---|
| summary | Some sources write titles, others rely on details only |
| aliases | Some advisories have no CVE |
| credits | Depends on how each source records reporters |
| ranges and versions | Each source picks a representation |
| severity | Not every record includes a rating |
Steps to run this audit on your own ecosystem
- Download the ecosystem archive and note its Last-Modified time.
- Read each JSON file and test each optional field for a non-empty value.
- Count records, including withdrawn ones, and count withdrawn separately.
- Build a table with one row per ecosystem.
- Add a sentence on how you defined present.
- Publish the script with the table.
Why this matters to a scanner user
If a tool depends on a field that is empty for your ecosystem, you may see fewer findings or less detail than you expect. Before you compare tools or ecosystems, check which fields the underlying records carry. Completeness is not quality, but it sets the ceiling on what any tool can show. For a quick way to see which advisories sit behind a result, see which advisory sources sit behind an SCA result.
Try it yourself
Click through it at your own pace, or open it full screen. Notice how much of a finding depends on the advisory record having the right package and version fields.
Quick check
Does a missing summary mean a bad advisory?
No. It means the record has no short title. The details field may still be complete.
Can I compare completeness across ecosystems?
Yes, with care. Each source follows its own practice, so a gap can reflect process, not quality.
Is a 100 percent summary rate a sign of quality?
It signals that the source writes a summary for every record. It says nothing about whether the summary is accurate or useful.
Sources
- OSV data documentation, https://google.github.io/osv.dev/data/ (fetched 19 October 2026).
- OpenSSF OSV schema, https://ossf.github.io/osv-schema/ (fetched 19 October 2026).
- OSV per-ecosystem exports, https://osv-vulnerabilities.storage.googleapis.com/ECOSYSTEM_NAME/all.zip for PyPI, crates.io, Go, RubyGems and Packagist (fetched 19 October 2026; counts computed by the author).
Last reviewed: 19 October 2026.