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'.
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 identifierignoreUntil(optional): after this date it is reported againreason(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.
| Flag | What it does |
|---|---|
--offline | Fully offline. Judges against a previously downloaded local database, does not update it, and sends no project or dependency information anywhere |
--offline-vulnerabilities | Only the vulnerability matching is offline; other work (such as transitive resolution) may still use the network |
--download-offline-databases | Permits 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 errors and what causes them
databases can only be downloaded when running in offline mode→--download-offline-databaseswas passed on its own; it needs an offline flag alongside it--offlinewith no local database yet → you get an error saying the database is missing; the first run has to fetch itno package sources found→ nothing at that path was recognised as a lockfile or manifest; name it with-Lor walk with-r
Choosing without guessing
- Air-gapped run →
--offline(plus--download-offline-databaseson the first run) - Only the vulnerability data must stay local →
--offline-vulnerabilities - Pin where the database lives → the
OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORYenvironment variable - Debugging → run with no flags first, then narrow
How it differs from the neighbours
| Tool | Data it reads | What it is good at |
|---|---|---|
| osv-scanner | OSV.dev | Across ecosystems, per lockfile, can run offline |
npm audit / pnpm audit | npm advisory database | Immediate for npm projects, nothing extra to install |
| Dependabot | GitHub Advisory | Opens update PRs — proposes the fix, not just the finding |
| Trivy | Several (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
- OSV-Scanner documentation — Usage / Offline Mode / Configuration
- Supported Artifacts and Manifests
Read next
- Getting started: installing and using osv-scanner
- Prioritisation: deciding what to patch first (CVSS, EPSS, KEV)
- Practice: the practice of vulnerability response / defending against npm supply-chain worms
FAQ
QDoes osv-scanner support pnpm-lock.yaml?
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?
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'?
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?
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.