An OSV advisory states which versions are affected with a range of one of three types: SEMVER, ECOSYSTEM or GIT. Events such as introduced and fixed mark the edges. Most scan errors in this area come from how a tool compares versions, or from records that use last_affected instead of fixed.
The three range types
The OSV schema defines the type field as required, and it controls how the values are read.
| Type | Values are | Comparison rule |
|---|---|---|
| SEMVER | SemVer 2.0.0 strings, no leading v | Semantic versioning order |
| ECOSYSTEM | Plain strings | The package ecosystem's own ordering |
| GIT | Full commit hashes | Needs the repository's commit graph |
For ECOSYSTEM ranges the schema notes that questions about inclusion may not be answerable without the ecosystem's own logic, which is why a versions list is recommended. GIT ranges still require an explicit versions list because they cannot be evaluated without a copy of the repository.
The events
- introduced starts the vulnerable range. The value 0 sorts before every other version.
- fixed is the first version containing the fix, and the schema says it is overwhelmingly preferred.
- last_affected is the highest affected version at the time of publication when no fix exists.
- limit sets an upper bound. For linear version ranges the schema says it should not be used.
A version is affected if it lies within any one range or appears in the versions list.
Where false negatives come from
The schema itself flags one risk. With last_affected, versions above the stated value are treated as unaffected, which "opens up the possibility for false negatives." If a vulnerability turns out to affect a later release, a record that named a last affected version can understate it until someone updates the record.
For GIT ranges, the schema says fixed events must include cherry picked fixes on every branch, or false positives result, while using limit instead can cause false negatives.
A third source is the scanner. If a tool applies SemVer ordering to a package that follows another scheme, it can place a version on the wrong side of a boundary. See why Python and SemVer versions sort differently.
How to check a record you care about
- Open the advisory in its source database and view the raw OSV JSON.
- Note the range type and the event that ends the range.
- If it uses last_affected, look at the upstream project for later releases and read their notes.
- Test your scanner on one version just inside and one just outside each boundary.
Safeguard's dependency scanning matches component versions against advisory data, and you can try a manifest at https://gold.safeguard.sh/scan.
Quick check
What is the difference between fixed and last_affected?
Fixed names the first version with the fix. Last_affected names the highest known affected version when no fix exists, and versions above it are treated as unaffected.
Why do GIT ranges need a repository?
Commit hashes cannot be ordered without the commit graph, so a tool needs the repository to decide whether a version falls in the range.
Sources
Last reviewed: 19 October 2026.