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:

  1. Flag Parsing: CLI arguments populate GetterOpts with offline=true and download-offline-databases values.

  2. Matcher Construction: The scan command calls NewLocalMatcher with downloadDB set to !offline (false when offline). If --download-offline-databases is combined with --offline, downloadDB becomes true only for the initial fetch.

  3. Database Initialization: For each ecosystem, matcher.loadDBFromCache creates a ZipDB via NewZippedDB with offline = !downloadDB and StoredAt pointing to the local zip path.

  4. Archive Loading: ZipDB.load invokes fetchZip. In offline mode, this validates file existence and returns *os.File for the local archive, or ErrOfflineDatabaseNotFound if missing.

  5. Vulnerability Matching: The scanner calls VulnerabilitiesAffectingPackage against the in-memory ZipDB.Vulnerabilities slice, 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.go orchestrates offline operations by managing cache directories and loading local databases.
  • ZipDB in internal/clients/clientimpl/localmatcher/zip.go implements the offline archive handling logic, returning ErrOfflineDatabaseNotFound when files are missing in offline mode.
  • The --offline flag disables all network access, while --offline-vulnerabilities restricts only the vulnerability lookup phase.
  • Cache storage follows the pattern <cache>/osv-scanner/<ecosystem>/all.zip, configurable via the OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY environment variable.
  • Offline mode requires pre-downloaded databases or the --download-offline-databases flag 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →