Of 44,476 non-malware advisory records in the OSV dumps for seven ecosystems, 13,910 (31%) have no GHSA-style severity label. The gap is largest for PyPI (55%), Go (48%) and crates.io (45%), where many records come from ecosystem databases that do not use that field. A missing label is not a low severity.
Method
We downloaded the per-ecosystem OSV dumps on 19 October 2026 and set aside the malware records (IDs starting MAL). That left 44,476 advisory records: PyPI 14,533, Go 9,641, npm 7,846, Maven 7,190, crates.io 2,923, NuGet 1,183 and RubyGems 1,160. We read the database_specific.severity label (LOW, MODERATE, HIGH or CRITICAL), which GitHub advisory records carry. For a few ecosystem databases we also checked whether the record carries a top-level severity list with a scoring vector. Counts are records, and some vulnerabilities have several records, which a related post covers.
Missing labels by ecosystem
| Ecosystem | Records | No label | Share |
|---|---|---|---|
| PyPI | 14,533 | 7,954 | 55% |
| Go | 9,641 | 4,633 | 48% |
| crates.io | 2,923 | 1,319 | 45% |
| npm | 7,846 | 3 | under 1% |
| Maven | 7,190 | 1 | under 1% |
| NuGet | 1,183 | 0 | 0% |
| RubyGems | 1,160 | 0 | 0% |
The pattern follows the record prefix. Every unlabelled PyPI record is a PYSEC or OSV record (7,942 and 12), none is a GHSA record. Every unlabelled Go record is from the Go vulnerability database (4,632) or one OSV record. Every unlabelled crates.io record is a RUSTSEC record (1,319). The label is a GitHub convention, not an OSV requirement.
Scoring vectors fill part of the gap
Some of those records carry a scoring vector instead of a label. In our read, 5,057 of the 7,942 PYSEC records (64%) have a top-level severity list, as do 478 of 1,319 RUSTSEC records (36%). None of the 4,632 Go database records do. For those, a team that wants a number must compute or look it up.
The labels that do exist
Among labelled records, the share rated CRITICAL is 19% for npm, 13% for Maven, 12% for PyPI GHSA records and 11% for Go GHSA records (npm 1,455 of 7,846, Maven 958 of 7,190, PyPI 816 of 6,579, Go 569 of 5,008). A higher share can mean the ecosystem has worse flaws, or that the labelled subset is different, so we do not rank ecosystems from it.
Triage when the label is missing
- Do not treat a blank as zero. Sort blanks into their own bucket and look at them.
- Check whether the same flaw has another record, often a GHSA or CVE alias, that carries a rating.
- Use exploitation evidence and reachability, which tell you more than a base rating does.
- Record the rule you used so a reviewer can see it was applied the same way to all.
Severity is one input. A flaw in a function you never call, or one that needs access an attacker lacks, can matter less than its label suggests.
Safeguard's SBOM and dependency scanning lists the components you run, and reachability analysis helps separate vulnerable code your application calls from code it does not. You can try a free scan at gold.safeguard.sh/scan.
Try it yourself
Click through it at your own pace, or open it full screen.
Open the queue and look at how findings are ordered when a severity and an exploit signal disagree.
Quick check
Does a missing severity label mean the flaw is minor?
No. It usually means the source database does not use that field. Look for an alias record or a score vector.
Can I compare ecosystems by CRITICAL share?
Not safely. The labelled subset differs by ecosystem, so the shares do not measure comparable populations.
Sources
- OSV data sources and dumps, per-ecosystem OSV dumps downloaded on 19 October 2026.
Last reviewed: 19 October 2026.