# How OSV-Scanner Performs Offline Scanning with Local Vulnerability Databases

> Learn how OSV-Scanner performs offline scanning using local vulnerability databases and cached zip archives. Discover secure scanning without network requests.

- Repository: [Google/osv-scanner](https://github.com/google/osv-scanner)
- Tags: how-to-guide
- Published: 2026-04-25

---

**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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/cmd/osv-scanner/internal/helper/flags.go), with values propagated through [`cmd/osv-scanner/internal/helper/getters.go`](https://github.com/google/osv-scanner/blob/main/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.

```bash

# 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:

```bash

# 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:

```bash
osv-scanner --offline-vulnerabilities ./my-project

```

### Programmatic Offline Usage

Integrate offline scanning into Go applications using the same code path as the CLI:

```go
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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/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.