OSV-Scanner
Overview
OSV-Scanner is a free, open-source vulnerability scanner from Google that queries the OSV.dev database — a distributed, open vulnerability database covering over 20 package ecosystems (npm, PyPI, Go, Maven, crates.io, NuGet, RubyGems, etc.) and aggregating data from GitHub Security Advisories, NVD, GHSA, CVE.org, and ecosystem-specific feeds. It scans lockfiles, SBOM files, container images, git repository histories, and directories. The guided remediation feature (osv-scanner fix) proposes the minimal version bumps to resolve vulnerabilities.
Installation
Go install (latest)
go install github.com/google/osv-scanner/cmd/osv-scanner@latest
osv-scanner --version
GitHub Releases (binary)
# Linux x86_64
curl -LO https://github.com/google/osv-scanner/releases/latest/download/osv-scanner_linux_amd64
chmod +x osv-scanner_linux_amd64
sudo mv osv-scanner_linux_amd64 /usr/local/bin/osv-scanner
Homebrew (macOS / Linux)
brew install osv-scanner
Docker
docker run --rm -v "$(pwd):/src" ghcr.io/google/osv-scanner --lockfile /src/package-lock.json
Verify installation
osv-scanner --version
osv-scanner --help
Configuration
osv-scanner.toml (project-level)
[[IgnoredVulns]]
id = "GO-2023-1840"
reason = "Not reachable in our usage pattern"
[[IgnoredVulns]]
id = "GHSA-1234-abcd-5678"
ignoreUntil = 2024-06-01 # Auto-expire ignore
reason = "Upstream fix pending, tracked in JIRA-123"
[IgnorePackages]
# Ignore all vulns for this package
[[IgnorePackages.packages]]
name = "vendored-library"
ecosystem = "npm"
reason = "Internal fork, managed separately"
[Licenses]
# License compliance checking
allowlist = ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC"]
deny = ["GPL-2.0", "GPL-3.0", "AGPL-3.0"]
Config file discovery
osv-scanner looks for osv-scanner.toml in:
- Directory explicitly passed via
--config - Each scanned directory (walking up to repo root)
~/.config/osv-scanner/config.toml
Core Commands
| Command | Description |
|---|---|
osv-scanner scan --lockfile package-lock.json | Scan an npm lockfile |
osv-scanner scan --lockfile requirements.txt | Scan Python requirements |
osv-scanner scan --lockfile go.sum | Scan Go module lockfile |
osv-scanner scan --lockfile Cargo.lock | Scan Rust Cargo lockfile |
osv-scanner scan --lockfile yarn.lock | Scan Yarn lockfile |
osv-scanner scan --lockfile poetry.lock | Scan Poetry lockfile |
osv-scanner scan --lockfile pnpm-lock.yaml | Scan pnpm lockfile |
osv-scanner scan --dir . | Scan directory for lockfiles automatically |
osv-scanner scan --recursive . | Recursively scan all lockfiles |
osv-scanner scan --sbom sbom.json | Scan a CycloneDX or SPDX SBOM |
osv-scanner scan --docker myapp:latest | Scan a Docker image |
osv-scanner scan --git-commit abc123f | Scan at a specific commit |
osv-scanner fix | Guided remediation (suggest version bumps) |
osv-scanner scan -f json . | JSON output |
osv-scanner scan -f sarif . | SARIF output |
osv-scanner scan --fail-on-vuln . | Exit non-zero if vulns found |
osv-scanner scan --config custom.toml . | Use custom config |
osv-scanner scan --experimental-call-analysis . | Enable call graph analysis |
osv-scanner scan --offline . | Offline mode (use local DB) |
osv-scanner scan --licenses-summary . | License compliance report |
Advanced Usage
Supported lockfile formats
| File | Ecosystem |
|---|---|
package-lock.json | npm |
yarn.lock | npm (Yarn) |
pnpm-lock.yaml | npm (pnpm) |
requirements.txt | PyPI |
Pipfile.lock | PyPI |
poetry.lock | PyPI |
go.sum | Go |
Cargo.lock | Rust (crates.io) |
Gemfile.lock | RubyGems |
composer.lock | Packagist (PHP) |
pubspec.lock | pub.dev (Dart/Flutter) |
packages.lock.json | NuGet |
pom.xml | Maven |
build.gradle | Gradle |
conan.lock | Conan (C/C++) |
mix.lock | Hex (Elixir) |
Guided remediation (osv-scanner fix)
# Interactive mode: suggests minimal version bumps
osv-scanner fix --lockfile package-lock.json
# Non-interactive: apply fixes automatically
osv-scanner fix --lockfile package-lock.json --non-interactive
# Preview only (no changes)
osv-scanner fix --lockfile package-lock.json --dry-run
# Fix for specific ecosystem
osv-scanner fix --lockfile go.sum
# Fix with Maven/Gradle (requires Java build tool)
osv-scanner fix --lockfile pom.xml
Call graph analysis (experimental)
# Reduces false positives by checking if vulnerable code is reachable
# Supported: Go, Rust (Cargo)
# Go call graph analysis
osv-scanner scan --experimental-call-analysis --lockfile go.sum
# Combined with directory scan
osv-scanner scan --experimental-call-analysis --dir ./mygoapp/
# The output marks each vuln as:
# CALLED / UNCALLED / UNKNOWN
Git repository scanning
# Scan entire git history for lockfiles at past commits
osv-scanner scan --recursive --git .
# Scan at a specific commit hash
osv-scanner scan --git-commit 9f8e7d6c .
# Scan between commits (find when a vuln was introduced)
osv-scanner scan --git-commit HEAD~50 --lockfile go.sum
Container image scanning
# Scan a Docker image (pulls if not cached)
osv-scanner scan --docker alpine:3.19
osv-scanner scan --docker nginx:latest
osv-scanner scan --docker myapp:production
# Save image and scan tarball
docker save myapp:latest | osv-scanner scan --docker -
SBOM scanning
# CycloneDX JSON
osv-scanner scan --sbom bom.json
# SPDX JSON
osv-scanner scan --sbom sbom.spdx.json
# SPDX TV format
osv-scanner scan --sbom sbom.spdx
# Generate SBOM with Syft then scan
syft myapp:latest -o cyclonedx-json > sbom.json
osv-scanner scan --sbom sbom.json
Output formats
# Default table output
osv-scanner scan --lockfile go.sum
# JSON (detailed, machine-readable)
osv-scanner scan -f json --lockfile go.sum | jq '.results[].packages[].vulnerabilities[]'
# SARIF (GitHub Code Scanning / Azure DevOps)
osv-scanner scan -f sarif --lockfile go.sum > osv-results.sarif
# Markdown (for PR comments)
osv-scanner scan -f markdown --lockfile go.sum
# Vertical (compact human-readable)
osv-scanner scan -f vertical --lockfile go.sum
Offline mode
# Download vulnerability database for offline use
osv-scanner download-vulns --dir ./vuln-db/
# Scan in offline mode with local DB
osv-scanner scan --offline --local-db-path ./vuln-db/ --lockfile go.sum
# Useful for air-gapped CI environments
License compliance
# Report all licenses found
osv-scanner scan --licenses-summary --lockfile package-lock.json
# Block on disallowed licenses (uses config allowlist)
osv-scanner scan --experimental-licenses --lockfile package-lock.json
# With config specifying allowed licenses
# See osv-scanner.toml [Licenses] section above
Common Workflows
GitHub Actions integration
name: OSV-Scanner
on:
push:
branches: [main]
pull_request:
schedule:
- cron: '0 6 * * *' # Daily at 6 AM
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write # Required for SARIF upload
contents: read
steps:
- uses: actions/checkout@v4
- name: Run OSV-Scanner
uses: google/osv-scanner-action@v1
with:
scan-args: |-
--recursive
--format=sarif
--output=results.sarif
./
continue-on-error: true
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
PR diff scanning (only new vulns)
- name: OSV-Scanner PR diff
uses: google/osv-scanner-action/osv-scanner-pr-action@v1
with:
scan-args: --recursive ./
Pre-commit hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/google/osv-scanner
rev: v1.7.0
hooks:
- id: osv-scanner
args: ['--recursive', '.']
Multi-lockfile project scan
#!/bin/bash
# scan-all.sh
set -e
echo "Scanning Python dependencies..."
osv-scanner scan --lockfile poetry.lock
echo "Scanning Node dependencies..."
osv-scanner scan --lockfile package-lock.json
echo "Scanning Go dependencies..."
osv-scanner scan --lockfile go.sum
echo "All scans passed."
Comparing OSV-Scanner vs Grype vs Snyk
| Feature | OSV-Scanner | Grype | Snyk |
|---|---|---|---|
| Cost | Free | Free | Freemium |
| Database | OSV.dev (open) | Anchore + NVD | Snyk DB (proprietary) |
| Call graph | Yes (Go, Rust) | No | Yes (partial) |
| Guided fix | Yes | No | Yes |
| Container scanning | Yes | Yes (primary) | Yes |
| SBOM input | Yes | Yes | Yes |
| License checks | Yes | No | Yes |
| Offline support | Yes | Yes | No |
| CI actions | Official | Via Anchore | Official |
Tips and Best Practices
Use --recursive for monorepos. A single osv-scanner scan --recursive . will discover and scan all lockfiles in the repository tree. Combine with --fail-on-vuln for CI gating.
Enable call graph analysis for Go and Rust. --experimental-call-analysis dramatically reduces false positives by only flagging vulnerabilities in code paths that are actually reachable. It is slower but highly recommended for Go services.
Use osv-scanner fix before opening a security PR. The guided remediation tells you the exact minimal version change to resolve each vulnerability, saving hours of manual dependency tree analysis.
Scan on every PR with diff mode. Use osv-scanner-pr-action to only alert on vulnerabilities introduced by the current PR, not existing baseline findings. This keeps PR checks relevant.
Set ignoreUntil on exceptions. When you accept a risk temporarily, always set an expiry date. This forces revisiting the decision and prevents forget-and-ignore accumulation.
Prefer lockfile scanning over manifest scanning. Scanning poetry.lock vs pyproject.toml gives exact versions rather than version ranges, resulting in far more accurate and actionable results.
Integrate with OSV.dev for deeper research. When a CVE appears, visit https://osv.dev/vulnerability/GO-2023-XXXX for full details, affected version ranges, and upstream patches.
Use SARIF in GitHub for code review context. SARIF output uploaded to GitHub Advanced Security shows vulnerabilities annotated on the relevant line of the lockfile in pull request diffs.