Skip to content
>_ITDITDWeb Security Platform

Security Guides

osv-scanner in Practice — pnpm, Ignoring CVEs, Offline Mode, and the Errors You Hit

The second-day questions: pnpm-lock.yaml support, ignoring a single CVE via osv-scanner.toml, and what the three offline flags actually do — including the cause of 'databases can only be downloaded when running in offline mode'.

Published 2026-09-04 Updated 2026-09-04 Last verified 2026-09-04 6 min read

Who this is for: people who have already installed osv-scanner and hit friction. This covers the second-day questions, not the install. Everything here follows the official documentation.

Pointing it at a lockfile

# a single lockfile
osv-scanner scan source -L pnpm-lock.yaml
 
# walk a directory
osv-scanner scan source -r ./my-project/

When the format cannot be inferred from the filename, prefix the path with the parser to use:

# parse an oddly named file as requirements.txt
osv-scanner scan source -L 'requirements.txt:/path/to/extra-requirements.txt'
 
# path containing a colon — lead with a bare ':' to keep filename inference
osv-scanner scan source -L ':/path/to/my:projects/package-lock.json'

Why the lockfile and not the manifest

A manifest (package.json and friends) records the range you asked for, not what actually got installed. A lockfile carries resolved, exact versions, so the scan matches what is really in the tree. Judging a range and hoping is far weaker evidence.

Ignoring a specific vulnerability

Drop an osv-scanner.toml into the directory being scanned:

[[IgnoredVulns]]
id = "GHSA-xxxx-xxxx-xxxx"
ignoreUntil = 2026-12-31
reason = "Feature is not used and the code path is unreachable; re-evaluate at the December inventory"
  • id (required): the vulnerability identifier
  • ignoreUntil (optional): after this date it is reported again
  • reason (optional): write it anyway — for the next person, who is usually you

--config=/path/to/config.toml overrides the per-directory files and applies everywhere. Note that ignoring a vulnerability also ignores the ones treated as its aliases.

An ignore is a deferral with a date, not a delete

An entry without ignoreUntil is an item that vanishes permanently and that nobody revisits. Our rule is: every ignore carries an expiry and a reason — when the date passes it comes back, so the deferred decision cannot be quietly forgotten. Open-ended ignores added to silence CI are exactly what turns into an incident six months later.

Offline mode: three flags, three jobs

This is where most confusion lives.

FlagWhat it does
--offlineFully offline. Judges against a previously downloaded local database, does not update it, and sends no project or dependency information anywhere
--offline-vulnerabilitiesOnly the vulnerability matching is offline; other work (such as transitive resolution) may still use the network
--download-offline-databasesPermits fetching/updating the local database — only effective when an offline flag is also set

--offline

fully offline; no database update, nothing sent out

--offline-vulnerabilities

only the matching is local; other work may use the network

--download-offline-databases (inert alone)

needs one of the above → on its own you get "databases can only be downloaded when running in offline mode"

The three offline flags. --download-offline-databases does nothing on its own — that is the error people search for.

The errors and what causes them

  • databases can only be downloaded when running in offline mode--download-offline-databases was passed on its own; it needs an offline flag alongside it
  • --offline with no local database yet → you get an error saying the database is missing; the first run has to fetch it
  • no package sources found → nothing at that path was recognised as a lockfile or manifest; name it with -L or walk with -r

Choosing without guessing

  • Air-gapped run--offline (plus --download-offline-databases on the first run)
  • Only the vulnerability data must stay local--offline-vulnerabilities
  • Pin where the database lives → the OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY environment variable
  • Debugging → run with no flags first, then narrow

How it differs from the neighbours

ToolData it readsWhat it is good at
osv-scannerOSV.devAcross ecosystems, per lockfile, can run offline
npm audit / pnpm auditnpm advisory databaseImmediate for npm projects, nothing extra to install
DependabotGitHub AdvisoryOpens update PRs — proposes the fix, not just the finding
TrivySeveral (incl. OSV)Container images and OS packages as well as app dependencies

Choosing exactly one is the mistake. Different databases surface different things. We run pnpm audit as the daily gate and use osv-scanner for cross-lockfile checks.

This site's view: a scanner will not tell you your pin went stale

One trap only shows up in real operation. When you pin a transitive dependency to an exact version with overrides, that package stops receiving patch updates — and a scanner only speaks up when a known vulnerability exists. So "the version you froze is now old" is a state nobody reports. We walked into this three times before adding our own daily check that compares every pin against the newest patch in its major line. A scanner shows today's holes; the conditions that become tomorrow's holes need a different mechanism.

Sources

FAQ

QDoes osv-scanner support pnpm-lock.yaml?
A

Yes. npm, yarn and pnpm lockfiles are all supported. Point at one directly with `osv-scanner scan source -L pnpm-lock.yaml`, or walk a tree with `-r`.

QHow do I ignore a single CVE?
A

Put an `osv-scanner.toml` in the scanned directory and add an `[[IgnoredVulns]]` entry with the `id`. You can also set `ignoreUntil` (an expiry date) and `reason`, so an exception records when and why rather than disappearing forever. Passing `--config=/path/to/config.toml` overrides the per-directory files and applies globally.

QWhy do I get 'databases can only be downloaded when running in offline mode'?
A

Because `--download-offline-databases` only takes effect when an offline flag is also set — it is not usable on its own. Combine it with the offline flag when you want the local database fetched as part of the run.

QIf I already have npm audit and Dependabot, do I need osv-scanner?
A

They read different databases and cover different ground. npm audit uses the npm advisory database and is npm-only; Dependabot mainly proposes updates on GitHub; osv-scanner reads OSV.dev across ecosystems (npm, PyPI, Go, Maven and more), works per lockfile, and can run fully offline. One catching something the other misses is normal, so treat them as different jobs rather than picking one.