Updated: 2026-07-07

OSV-Scanner[1] is the Google tool, announced in 2022[2], that directly queries the open OSV.dev database to identify vulnerabilities in project dependencies. At first glance it looks like any other dependency scanner, and indeed the output is similar. The difference lies beneath, in how vulnerability data is represented and how cross-referencing with real dependencies happens. After two years using it on several projects, this article collects why this structure produces less noise than other tools and where friction remains.

Key takeaways

  • Version-based scanners generate many false positives because the affected-version lists in original CVE advisories are often imprecise or generic.

  • OSV represents each vulnerability with precise commit or semantic version ranges, enabling deterministic comparisons.

  • OSV-Scanner supports the most common manifests: npm, Python, Go, Ruby, PHP, Rust, Maven, Gradle; also container images and SBOMs in SPDX or CycloneDX.

  • The most valuable CI integration is failing only on new vulnerabilities introduced by the current change, not on preexisting ones.

  • The scanner is an important part of a system, not the whole system.

The version-based scanner problem

Many dependency scanners work by comparing the version you use against a list of affected versions for each CVE. That sounds reasonable but generates a surprising number of false positives. There are several reasons for this:

  • The affected-version lists in original CVE advisories are often imprecise or generic.

  • Linux distributions backport patches without changing the public package version, so a scanner can think a version is vulnerable when it has actually already been patched.

  • An advisory may apply only to certain configurations or uses of the component, and the scanner does not distinguish between them.

The practical result is familiar to any team: dependency scanners produce hundreds or thousands of alerts, a mix of real and false, and filtering the real ones consumes so much time that many teams end up ignoring the scanner. Signal is lost in noise. It is the same underlying problem we describe when talking about CVE-based attack surface management: a list of identifiers with no context is not a prioritized work queue.

OSV as a structured format

The idea behind OSV is to change how vulnerability data is represented. Instead of a free-prose advisory with a vague list of affected versions, each vulnerability in OSV has a structured format with:

  • Precise commit or semantic version ranges.

  • Stable identifiers for each package and ecosystem.

  • Cross-references to the original advisories.

This structure allows deterministic comparisons between what a project has and what is listed as affected. A concrete example: an OSV advisory for a vulnerability in an npm package specifies exactly that versions between 1.2.0 and 1.4.5 are affected, in exact SemVer format. If your project uses version 1.4.6, the comparison is deterministic: not affected. No room for ambiguity.

OSV.dev[3] aggregates advisories from multiple sources while keeping this structure: GitHub Security Advisories, the PyPI Advisory Database, ecosystem-specific sources like RustSec, and the Global Security Database. Aggregating is not just pooling them together, it means normalizing them to the OSV format[4] and cross-referencing them.

How OSV-Scanner works

OSV-Scanner takes the dependency manifest of your project, resolves the exact versions, and queries OSV.dev for each package-and-version combination. The query returns the list of OSV advisories that apply exactly to those versions. There is no heuristic version matching and no free interpretation: if it shows up in the response, it applies.

The scanner supports the most common manifests:

  • npm’s package-lock.json.

  • Python’s requirements.txt and poetry.lock.

  • Go’s go.mod and go.sum.

  • Ruby’s Gemfile.lock.

  • PHP’s composer.lock.

  • Rust’s Cargo.lock.

  • Maven’s pom.xml.

  • Gradle’s gradle.lockfile.

It can also scan container images by inspecting installed packages, and SBOM files in SPDX or CycloneDX format.

Practical CI use

CI integration is one of the places where it shines most. OSV-Scanner is a static binary that can run in any environment. The typical pattern is adding a pipeline step that runs osv-scanner against the repository and fails the build if vulnerabilities matching certain criteria show up.

The most useful criteria in practice are two:

  • Fail if any vulnerability is listed in the CISA KEV catalog[5] (Known Exploited Vulnerabilities), because that indicates it is already being exploited in production.

  • Fail if vulnerabilities introduced by the current change appear, meaning vulnerabilities that did not exist on the main branch and show up because of dependencies added or updated on this branch. This second criterion is far more useful than failing on preexisting vulnerabilities, because it lets the baseline move forward without every existing security fix blocking every commit.

Another useful practice is running the scan more often than commits happen, for example once a day against the main branch. Vulnerabilities published after a commit passed CI can appear at any time. OSV-Scanner covers declared dependencies; for vulnerabilities in your own code, the complementary layer is a static analyzer like Semgrep, which checks for insecure code patterns instead of dependency manifests.

What about uncovered ecosystems

A valid criticism is that ecosystem coverage is not uniform. npm, PyPI, Maven, and Go are covered very well. Rust and Ruby are covered well. PHP and NuGet are covered adequately. But there are ecosystems where coverage is partial or nonexistent.

For these cases there are two strategies: complementing OSV-Scanner with other ecosystem-specific tools, or contributing to OSV.dev, which accepts advisory contributions.

For most projects with dependencies in the largest ecosystems, OSV-Scanner is enough as the primary tool. For projects with dependencies in less mainstream ecosystems, it is worth having at least a second layer. This connects with the defense-in-depth approach we describe in guardrails in LLMs: frameworks and their real cost.

The relationship with SBOMs

OSV-Scanner works very well with SBOMs. You can pass it an SBOM file in SPDX or CycloneDX format as input, and it produces the same kind of report as if it had started from the manifests. This is especially useful when the build process generates SBOMs and you want to scan starting from them, or when you want to scan artifacts already deployed for which you only have the SBOM.

The architecture that works across several projects is: the build chain generates SBOMs as part of the artifact, the SBOMs are stored in a registry alongside the artifact, and a periodic job runs OSV-Scanner against all the stored SBOMs to detect new vulnerabilities in artifacts already deployed.

Real limits

Three areas where OSV-Scanner keeps improving but is not yet enough:

  • The reach of runtime-based scanners: OSV-Scanner works on static declarations, manifests and SBOMs. It does not detect dependencies loaded dynamically at runtime, native system libraries the binary links against, or plugins.

  • Lack of context on whether a vulnerability affects your specific use: a CVE in an XML function of a library you only use for JSON does not affect you in practice, but OSV-Scanner will still report it.

  • The prioritization layer: OSV-Scanner reports vulnerabilities but does not rank them by real risk. Turning a list of vulnerabilities into a prioritized work queue still needs a layer on top.

My take

OSV-Scanner is the best available piece today for the basic step of scanning dependencies. Its value is in the source of truth it queries, OSV.dev, more than in the scanner itself. The combination produces significantly fewer false positives than traditional scanners.

The concrete recommendation is that any project with open source dependencies should have OSV-Scanner running in CI, at least in the mode that detects new vulnerabilities introduced by the current change. It is free, it is fast, and the data source is good.

Thinking that having it enabled already covers dependency scanning is a common mistake. The tool is an important part of a system, not the whole system. Seen that way, it is useful, stable, and reduces the alert fatigue that does so much damage to practical security.

Conclusion

Alert fatigue is the enemy of real security. OSV-Scanner attacks that problem at the root, using structured data instead of version heuristics. For teams today with a dependency scanner producing hundreds of ignored alerts, migrating to OSV-Scanner usually reduces noise to a manageable fraction without losing real coverage.

Sources

  1. OSV-Scanner
  2. announced in 2022
  3. OSV.dev
  4. OSV format
  5. CISA KEV catalog