How OSV-Scanner Performs Offline Scanning with Local Vulnerability Databases
OSV-Scanner performs offline scanning by loading vulnerability data from locally cached zip archives using the LocalMatcher and ZipDB components, eliminating all HTTP requests when the --offline flag is enabled.
The google/osv-scanner repository provides a complete offline scanning capability for air-gapped environments or security-sensitive workflows. By pre-downloading the Open Source Vulnerabilities (OSV) database as compressed archives, the tool can match packages against known vulnerabilities without network access.
Core Components for Offline Scanning
The offline architecture relies on three primary components that work together to replace remote API calls with local file system access.
LocalMatcher Orchestrates Cache Access
The LocalMatcher struct in internal/clients/clientimpl/localmatcher/localmatcher.go serves as the entry point for offline vulnerability matching. When constructed with offline=true, it instantiates ZipDB instances that read from disk rather than downloading data.
The matcher resolves cache directories via setupLocalDBDirectory, checking the OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY environment variable first, then falling back to the user cache directory (os.UserCacheDir) or temporary directory. It constructs paths following the pattern <cache>/osv-scanner/<ecosystem>/all.zip.
ZipDB Handles Archive Operations
ZipDB in internal/clients/clientimpl/localmatcher/zip.go wraps individual ecosystem databases. The fetchZip method checks the Offline field before attempting any network operations.
When Offline is true, the method opens the local zip file directly. If the file is missing, it returns ErrOfflineDatabaseNotFound immediately without attempting a download. This ensures strict offline compliance even when vulnerability data is stale or absent.
Cache Directory Resolution
The setupLocalDBDirectory function creates the base cache structure at <path>/osv-scanner. This directory stores ecosystem-specific subdirectories containing all.zip files downloaded from https://osv-vulnerabilities.storage.googleapis.com/<ecosystem>/all.zip.
CLI Flags Controlling Offline Mode
Flag definitions reside in cmd/osv-scanner/internal/helper/flags.go, with values propagated through cmd/osv-scanner/internal/helper/getters.go via the GetterOpts struct.
--offline: Disables all network features completely--offline-vulnerabilities: Disables only vulnerability lookups while allowing optional network steps like transitive dependency discovery--download-offline-databases: Permits downloading databases on first run even when offline flags are set
Step-by-Step Offline Scanning Workflow
The following sequence executes when running osv-scanner --offline:
-
Flag Parsing: CLI arguments populate
GetterOptswithoffline=trueanddownload-offline-databasesvalues. -
Matcher Construction: The scan command calls
NewLocalMatcherwithdownloadDBset to!offline(false when offline). If--download-offline-databasesis combined with--offline,downloadDBbecomes true only for the initial fetch. -
Database Initialization: For each ecosystem,
matcher.loadDBFromCachecreates aZipDBviaNewZippedDBwithoffline = !downloadDBandStoredAtpointing to the local zip path. -
Archive Loading:
ZipDB.loadinvokesfetchZip. In offline mode, this validates file existence and returns*os.Filefor the local archive, orErrOfflineDatabaseNotFoundif missing. -
Vulnerability Matching: The scanner calls
VulnerabilitiesAffectingPackageagainst the in-memoryZipDB.Vulnerabilitiesslice, completing the scan without network traffic.
Running Offline Scans
Execute a completely offline scan by pointing to a project directory. The command fails if local databases are missing.
# Optional: Specify custom cache location
export OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY=$HOME/.cache/osv-db
# Scan without network access
osv-scanner --offline ./my-project
Populate the cache initially while maintaining offline semantics for subsequent runs:
# Download databases on first run, then scan offline
osv-scanner --offline --download-offline-databases ./my-project
Use --offline-vulnerabilities when you need network access for dependency resolution but must keep vulnerability lookups local:
osv-scanner --offline-vulnerabilities ./my-project
Programmatic Offline Usage
Integrate offline scanning into Go applications using the same code path as the CLI:
import (
"context"
"github.com/google/osv-scanner/v2/internal/clients/clientimpl/localmatcher"
"github.com/google/osv-scanner/v2/internal/imodels"
"github.com/google/osv-scalibr/extractor"
)
// Create matcher with downloadDB=false for offline mode
matcher, err := localmatcher.NewLocalMatcher(
"", // Use default cache directory resolution
"my-osv-scanner", // User-Agent string
false, // downloadDB=false enables strict offline mode
)
if err != nil {
panic(err)
}
// Define packages to scan
pkgs := []*extractor.Package{
{Name: "github.com/gin-gonic/gin", Version: "v1.8.1"},
}
ctx := context.Background()
vulns, err := matcher.MatchVulnerabilities(ctx, pkgs)
if err != nil {
panic(err)
}
fmt.Println(imodels.FormatVulns(vulns))
Summary
- LocalMatcher in
internal/clients/clientimpl/localmatcher/localmatcher.goorchestrates offline operations by managing cache directories and loading local databases. - ZipDB in
internal/clients/clientimpl/localmatcher/zip.goimplements the offline archive handling logic, returningErrOfflineDatabaseNotFoundwhen files are missing in offline mode. - The
--offlineflag disables all network access, while--offline-vulnerabilitiesrestricts only the vulnerability lookup phase. - Cache storage follows the pattern
<cache>/osv-scanner/<ecosystem>/all.zip, configurable via theOSV_SCANNER_LOCAL_DB_CACHE_DIRECTORYenvironment variable. - Offline mode requires pre-downloaded databases or the
--download-offline-databasesflag for initial population.
Frequently Asked Questions
What is the difference between --offline and --offline-vulnerabilities?
--offline disables all network-dependent features entirely, ensuring zero outbound connections. --offline-vulnerabilities disables only the vulnerability database lookups while permitting other network operations like transitive dependency discovery through external package managers. Use the latter when you trust the local vulnerability cache but need dynamic dependency resolution.
Where does OSV-Scanner store local vulnerability databases?
By default, databases store in the OS-specific user cache directory under osv-scanner/<ecosystem>/all.zip. Override this location by setting the OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY environment variable before running the scanner. The setupLocalDBDirectory function in localmatcher.go implements this resolution logic, falling back to the system temporary directory if needed.
How do I download vulnerability databases for offline use?
Run the scanner with both --offline and --download-offline-databases flags. This combination allows the first execution to fetch zip files from https://osv-vulnerabilities.storage.googleapis.com while preparing the environment for subsequent strict offline scans. Alternatively, manually download ecosystem archives and place them in the expected cache directory structure.
Can I use OSV-Scanner offline in a CI/CD pipeline?
Yes. Pre-populate the cache directory in a build step with network access using --download-offline-databases, then copy the cached databases into your air-gapped or restricted CI environment. Subsequent scan jobs run with --offline flag pointing to the pre-populated cache location, ensuring reproducible security scanning without external dependencies.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →