google / google/osv-scanner

IsAffected panics on an advisory with an unrecognized ecosystem, crashing the whole scan

Closed
#2,867 4 comments 0 reactions 1 assignee Claimed by @Lougarou View on GitHub
Dominant language
Go
Stars
11k
Forks
792
Avg merge
1d 20h
Merged PRs (30d)
48

Description

### Summary

`vulns.IsAffected` panics when an OSV advisory's `affected[].package.ecosystem` is a value that `osvecosystem.MustParse` does not recognize. Because `IsAffected` is called for every advisory on the match path, a single such advisory aborts the entire scan instead of being skipped.

### Affected code

- `internal/utility/vulns/vulnerability.go:160` (and `:113` in `AffectsEcosystem`):
```go
if osvecosystem.MustParse(affected.GetPackage().GetEcosystem()).Equal(imodels.Ecosystem(pkg)) && ...
```
`osvecosystem.MustParse` panics (`Failed MustParse: base ecosystem does not exist in osvschema: "…"`) on any unrecognized ecosystem string.
- Reached from the normal local-DB match path: `internal/clients/clientimpl/localmatcher/zip.go:304` → `VulnerabilitiesAffectingPackage` → `IsAffected`, which loops over `v.GetAffected()` and calls `MustParse` on each entry.

### Reproduction

A recognized-ecosystem package matched against a **multi-ecosystem advisory** where one `affected[]` entry uses an ecosystem the build's vendored `osv-schema` doesn't know. The package isn't in-range for the known entry, so `IsAffected` falls through to the unknown entry and panics:

```go
vuln := &osvschema.Vulnerability{
Id: "EXAMPLE-multi",
Affected: []*osvschema.Affected{
{ // npm entry the package is NOT in-range for (5.0.0 <= v < 6.0.0)
Package: &osvschema.Package{Ecosystem: "npm", Name: "my-package"},
Ranges: []*osvschema.Range{{Type: osvschema.Range_ECOSYSTEM,
Events: []*osvschema.Event{{Introduced: "5.0.0"}, {Fixed: "6.0.0"}}}},
},
{ // ecosystem the vendored osv-schema does not know
Package: &osvschema.Package{Ecosystem: "SomeFutureEcosystem", Name: "other"},
Ranges: []*osvschema.Range{{Type: osvschema.Range_ECOSYSTEM,
Events: []*osvschema.Event{{Introduced: "0"}, {Fixed: "2.0.0"}}}},
},
},
}
pkg := &extractor.Package{Name: "my-package", Version: "1.0.0", PURLType: purl.TypeNPM}
vulns.IsAffected(vuln, pkg) // panics: base ecosystem does not exist in osvschema: "SomeFutureEcosystem"
```

### Why it's reachable (no attacker required)

OSV advisories routinely list multiple ecosystems in `affected[]`, and a per-ecosystem DB zip stores the full advisory record (all `affected[]` entries, not just the matching one). The vendored `osv-schema` ecosystem registry is pinned per osv-scanner release, while osv.dev's ecosystem set evolves over time. So once osv.dev introduces a new ecosystem that appears in a multi-ecosystem advisory, **older osv-scanner builds still pinned in CI will panic on it** — a forward-compatibility availability problem with a broad blast radius for a tool that runs in many CI pipelines. It is also deterministically triggerable today with a custom/local advisory database.

### Relationship to #2831 / #2837

#2837 fixed the *version*-parser panic — `semantic.Parse` is now skipped gracefully for ecosystems that have no version parser (e.g. GitHub Actions). This is a **different, still-present site**: the *ecosystem-name* `osvecosystem.MustParse` at `vulnerability.go:113` and `:160` was not changed and still panics on an unrecognized ecosystem string.

### Suggested fix

Use the non-panicking `osvecosystem.Parse` and skip the `affected[]` entry on error — the same "skip, don't panic on unsupported ecosystems" approach taken in #2837. The default (recognized) path is unaffected.

I have a fix and a reproducing test ready, and would be happy to open a PR once this is assigned.

---

This was found via automated state-space analysis and confirmed with a reproducing Go test against the current `main`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.