セキュリティ対策
osv-scanner の実務Q&A — pnpm対応・CVEの除外・オフライン実行・つまずくエラー
導入後に必ず出る質問だけ。pnpm-lock.yamlへの対応、特定CVEの除外(osv-scanner.toml の IgnoredVulns)、オフライン3フラグの違いと『databases can only be downloaded when running in offline mode』の原因を、公式仕様にもとづいて整理します。
対象:osv-scanner を導入したあとで、実際に回して詰まった人。導入手順ではなく、その次に出てくる質問だけを集めています。仕様は公式ドキュメントに準拠しています。
ロックファイルの指定
# 単一のロックファイルを指定
osv-scanner scan source -L pnpm-lock.yaml
# ディレクトリを再帰的に走査
osv-scanner scan source -r ./my-project/ファイル名から形式が推測できない場合は、形式:パス の形で「どのパーサで読むか」を明示できます。
# 変わった名前のファイルを requirements.txt として解釈させる
osv-scanner scan source -L 'requirements.txt:/path/to/extra-requirements.txt'
# パスにコロンが含まれる場合は、先頭を「:」だけにして推測に任せる
osv-scanner scan source -L ':/path/to/my:projects/package-lock.json'ロックファイルを指定する意味
マニフェスト(package.json など)は「欲しいバージョンの範囲」しか書いておらず、実際に入る版が確定しません。ロックファイルには解決済みの正確なバージョンが並ぶので、スキャン結果が「実際に入っているもの」と一致します。範囲だけを見て「たぶん大丈夫」と判定するより、はるかに信用できます。
特定のCVEを除外する
スキャンするディレクトリに osv-scanner.toml を置きます。
[[IgnoredVulns]]
id = "GHSA-xxxx-xxxx-xxxx"
ignoreUntil = 2026-12-31
reason = "該当機能を使っておらず、到達経路がないため。12月の棚卸しで再評価する"id(必須):脆弱性の識別子ignoreUntil(任意):この日付を過ぎると再び報告されますreason(任意):理由。将来の自分と他人のために必ず書く
--config=/path/to/config.toml を渡すと、走査対象の各ディレクトリに置いた設定より優先して全体に適用されます。なお、別名(エイリアス)として扱われている脆弱性もまとめて無視されます。
除外は“恒久的に消す”ではなく“期限を切って見送る”
ignoreUntil を書かない除外は、永久に消えたまま誰も気づかない項目になります。当サイトの運用ルールは「除外には必ず期限と理由を書く」——期限が来れば再び報告に出てくるので、判断を先送りしたことを忘れられません。CI を黙らせるためだけの無期限除外は、半年後に必ず事故のもとになります。
オフライン実行:3つのフラグの関係
ここが最も誤解されます。役割が違う3つがあります。
| フラグ | 何をするか |
|---|---|
--offline | 完全オフライン。事前に取得したローカルDBだけで判定し、DBの更新もせず、プロジェクトや依存の情報をどこにも送りません |
--offline-vulnerabilities | 脆弱性判定だけをローカルDBで行う。推移的依存の解決など他の処理はネットワークを使い得ます |
--download-offline-databases | ローカルDBの取得・更新を許可する。offline 系フラグと併用したときだけ有効 |
--offline
完全オフライン。DBの更新もせず、外へ何も送らない
--offline-vulnerabilities
脆弱性判定だけローカル。他の処理はネットを使い得る
--download-offline-databases(単体では無効)
上のどちらかと併用して初めて効く → 単体だと 「databases can only be downloaded when running in offline mode」
よくあるエラーと原因
databases can only be downloaded when running in offline mode→--download-offline-databasesを単体で指定した。offline 系フラグと併用が必要- ローカルDBが無い状態で
--offline→ 「DBが無い」というエラーになる。初回は取得が必要 no package sources found→ そのパスに認識できるロックファイル/マニフェストが無い。-Lで明示するか-rで再帰する
迷わないための指針
- 完全な閉域で回す →
--offline(+初回だけ--download-offline-databases) - CIで外に出したくないのは脆弱性判定だけ →
--offline-vulnerabilities - DBの置き場所を固定したい → 環境変数
OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY - まずローカルで動くか確認 → フラグ無しで実行してから絞る
他ツールとの使い分け
| ツール | 参照するデータ | 得意なこと |
|---|---|---|
| osv-scanner | OSV.dev | 複数エコシステム横断。ロックファイル単位、オフライン実行可 |
npm audit / pnpm audit | npm アドバイザリDB | npm系で手軽。追加インストール不要 |
| Dependabot | GitHub Advisory | 更新PRを自動で作る(検出だけでなく修正提案) |
| Trivy | 複数(OSV含む) | コンテナイメージやOSパッケージまで含めた広い走査 |
どれか1つに絞るのが誤りです。データベースが違えば拾うものも違います。当サイトは pnpm audit を日次の門番に、osv-scanner をロックファイル横断の確認に使い分けています。
当サイトの視点:スキャナは“ピンが古くなったこと”を教えてくれない
実運用で分かった落とし穴があります。推移的依存を overrides で特定バージョンに固定すると、以後そのパッケージはパッチ更新を受け取りません。そしてスキャナが警告するのは「既知の脆弱性がある」ときだけなので、固定したバージョンが古くなっただけの状態は、誰も教えてくれません。当サイトはこれを3回連続で踏み、最終的に「各ピンが同じメジャー内の最新パッチかどうか」を毎日照合する自前チェックを監査スクリプトに足しました。スキャナは「今の穴」を見る道具であって、「将来の穴になりやすい状態」は別の仕組みで見る必要がある——これが当サイトの結論です。
出典
- OSV-Scanner 公式ドキュメント — Usage / Offline Mode / Configuration
- Supported Artifacts and Manifests(対応ロックファイル一覧)
次に読む
- 導入:osv-scannerの導入と使い方(インストールからCI組込みまで)
- 優先度:CVEの直す順番はどう決めるか(CVSS・EPSS・KEVの使い分け)
- 実務:脆弱性対応の実務 / npmサプライチェーンワームへの防御
よくある質問
Qosv-scanner は pnpm-lock.yaml に対応していますか?
対応しています。npm/yarn/pnpm のロックファイルはいずれも対象で、`osv-scanner scan source -L pnpm-lock.yaml` のように直接指定できます。ディレクトリを再帰的に走査する場合は `-r` を使います。
Q特定のCVEだけ除外したいときは?
スキャン対象のディレクトリに `osv-scanner.toml` を置き、`[[IgnoredVulns]]` に `id` を書きます。`ignoreUntil`(期限)と `reason`(理由)も書けるので、恒久的に消すのではなく『いつまで・なぜ見送るか』を残せます。`--config=/path/to/config.toml` を渡すと、対象ディレクトリ内の設定より優先して全体に適用されます。
Q『databases can only be downloaded when running in offline mode』が出ます
`--download-offline-databases` は、offline 系のフラグと一緒に指定したときだけ有効になるためです。単体では使えません。ローカルDBを取得しながら実行したい場合は offline フラグと併用してください。
Qnpm audit や Dependabot があれば osv-scanner は不要ですか?
見ているデータベースと守備範囲が違います。npm audit は npm のアドバイザリDBで npm エコシステム限定、Dependabot は主に GitHub 上での更新提案、osv-scanner は OSV.dev を参照して複数エコシステム(npm/PyPI/Go/Maven など)を横断し、ロックファイル単位でオフライン実行もできます。片方が拾って片方が拾わない、は普通に起きるので、どれか1つに絞るのではなく役割で使い分けます。