Match an advisory's affected range to an SBOM version by reading the range type first, then testing the SBOM version with that type's ordering rules. A version is affected if it falls inside any listed range or appears in the advisory's explicit versions list. Do not compare version strings alphabetically.
What the range actually says
The OSV schema is a common way advisories express this. An affected entry can hold ranges and an explicit list of versions. A version counts as affected if it lies within any one of the ranges or is listed in the versions list.
Each range has a type, and the type decides how to compare:
| Range type | How values are read | Practical note |
|---|---|---|
| SEMVER | SemVer 2.0.0 versions | Ranges must not overlap |
| ECOSYSTEM | Strings in the package ecosystem's own ordering | Use the ecosystem's own comparison logic |
| GIT | Full commit hashes | Needs the repository history to evaluate |
Events inside a range mark the boundaries. introduced starts a vulnerable range, and the value 0 sorts before every other version. fixed is the first version that contains the fix. last_affected is the last known vulnerable version when the record was written. The schema notes that treating everything above last_affected as safe can cause false negatives if a fix lands later in a higher version.
Steps to match safely
- Read the range type before you compare anything.
- Use a comparison library for that ecosystem, not string sorting. "10.0.0" is lower than "9.0.0" alphabetically and higher numerically.
- Treat
introducedas inclusive andfixedas exclusive: the fixed version itself is not affected. - If the record has an explicit versions list, check it as well as the ranges.
- For GIT ranges, do not guess from a version label. Ask whether the build contains the fix commit.
- Record which source and which version of the advisory you used, since records get updated.
Pitfalls specific to SBOMs
SBOM versions are sometimes messy. A component may carry a distribution suffix, a build number, or no version at all. When the version is missing, you cannot place it inside or outside a range. Mark it as unknown and chase it, rather than assuming it is outside the range.
Backports also matter. A distribution may ship a patched build under an older version number. A range-based match then reports a false positive, and a vendor advisory or VEX statement for that package is the right way to settle it.
Writing the verdict
For each match, store the SBOM version, the range that matched, and the verdict: affected, not affected, or needs review. Keep reviewer notes short and factual. If the verdict is "not affected" for a reason other than version, such as code not being called, that belongs in a VEX statement with a justification, not in a version note.
Quick check
Is the fixed version itself affected?
No. The fixed event names the first version that contains the fix, so it sits outside the affected range.
What if the SBOM has no version for the component?
Treat the result as unknown and find the version from the build or lockfile. Do not assume it is safe.
Can I sort version strings as text?
No. Use the ecosystem's own ordering or a SemVer library, depending on the range type.
Safeguard's dependency scanning performs this matching for you across stored SBOMs, and the free scan at gold.safeguard.sh/scan shows how a result looks.
Sources
Last reviewed: 19 October 2026.