Google製OSV-ScannerをMCPサーバーとして使える「OSV-Scanner-MCP」の v0.11.0 をnpmで公開しました。
これまではJava(Maven / Gradle)専用でしたが、v0.4.0〜v0.11.0で Go・JavaScript・Python に対象を広げました。
1つのプロジェクトに複数の言語が混在していても、lockfileを検出してまとめてスキャンし、脆弱なパッケージごとに 推奨アップグレード版 まで提案します。
何が変わったか
| バージョン | 内容 |
|---|---|
| v0.4.0 | 新ツール scan_project: Java・JavaScript・Python・Goのlockfileをまとめてスキャン |
| v0.5.0 |
suggest_fix がnpm・Goに対応(Semantic Versioning) |
| v0.6.0 |
suggest_fix がPyPIに対応(PEP 440) |
| v0.7.0 | 直接依存か推移的依存かを判定(package-lock.json・go.mod・requirements.txt) |
| v0.8.0 | 推奨先の版をOSVに照会し、既知の脆弱性がある版を避ける |
| v0.9.0 | pom.xmlの直接/推移的依存の判定 |
| v0.10.0 | JAR/WARスキャンの改善、応答の縮小、Nodeの権限モデルでの動作 |
| v0.11.0 | README・ツールの説明・応答の文言を英語化 |
新ツール scan_project
プロジェクトのディレクトリを渡すと、配下のlockfile・マニフェストを検出してまとめてスキャンします。
{
"project_path": "/absolute/path/to/project"
}
| エコシステム | 対応ファイル |
|---|---|
| Java(Maven) |
pom.xml、gradle.lockfile
|
| JavaScript(npm) |
package-lock.json、npm-shrinkwrap.json、yarn.lock、pnpm-lock.yaml、bun.lock
|
| Python(PyPI) |
poetry.lock、uv.lock、Pipfile.lock、pdm.lock、requirements.txt
|
| Go | go.mod |
パッケージマネージャーやビルドは実行しません。
npm install や pip install はスクリプトの実行を伴うため、lockfileを読む方式に統一しています。そのため、lockfileがないプロジェクトはスキャンできない依存が出ます。
その代わり、応答の先頭の coverage に「スキャンできなかったもの」を明示します。
| 項目 | 意味 |
|---|---|
lockfile_missing |
lockfileのないマニフェスト(package.json、pyproject.toml 等)と、lockfileの生成手順 |
unpinned_requirements |
requirements.txtで版を固定していない行。>=X の行は下限Xでスキャンされます |
unscannable_requirements |
-e やURL指定など、スキャンされない行とその理由 |
skipped_files |
スキャン対象から外したファイルと理由 |
coverage.complete が false のときは、検出0件でも安全とは言えません。LLMがここを読み飛ばして「脆弱性はありません」と要約しないよう、範囲の情報を件数より前に置いています。
requirements.txtは元のファイルを渡さない
OSV-Scannerはrequirements.txtの -r(取り込み)を独自にたどります。- r ../x.txt のような空白入りの書き方も取り込みとみなすため、スキャン範囲の外のファイルが読まれることがありました。
そこで、元のファイルはOSV-Scannerに渡さず、本サーバーが解釈できた依存の行だけを 名前==版 の形に直した一時コピーをスキャンしています。取り込みは、プロジェクトディレクトリ内のものだけを本サーバーが展開します。
修正版の推奨 suggest_fix
脆弱なパッケージごとに、現在の版に最も近い系統の修正版 を推奨します。単純に最新版を勧めるのではなく、次の順で探します。
| Tier | 意味 |
|---|---|
same_minor |
同じ系統内の修正版(変更が最小) |
major_internal |
同じメジャー内の修正版(マイナーバージョンアップ) |
cross_major |
メジャーアップグレードが必要(破壊的変更の可能性あり) |
言語ごとにバージョンの比較規則が違うため、それぞれ実装しました。
- npm・Go: Semantic Versioning。Goの疑似バージョン(
0.0.0-20190813141303-74dc4d7220e7)や+incompatibleも扱います - PyPI: PEP 440。
1.8c1や2.8.0-rc0のような正規形でない表記も正規化します。PyPApackagingと2万組の比較で結果が一致することを確認しました -
0.x系の扱い: npmの
^(キャレット)に合わせ、0.xのマイナー更新(0.3→0.4)はcross_major(破壊的変更の可能性あり)としています
プレリリース版(canary版など)は、正式版で解消できない場合だけ推奨し、recommended_is_prerelease: true を付けます。
実データでの実行結果(例)
検証用のプロジェクトで実際に得た推奨です(2026年10月時点のOSVデータ。データの更新で変わります)。
| パッケージ | 現在の版 | 推奨 | Tier |
|---|---|---|---|
| lodash(npm) | 4.17.20 | 4.18.0 | major_internal |
| express(npm) | 4.17.1 | 4.20.0 | major_internal |
| next(npm) | 15.5.0 | 15.5.24 |
same_minor(canary版ではなく正式版) |
| golang.org/x/text(Go) | 0.3.0 | 0.39.0 |
cross_major(0.xのマイナー更新) |
| golang.org/x/net(Go) | 疑似バージョン | 0.56.0 | cross_major |
| requests(PyPI) | 2.19.0 | 2.33.0 | major_internal |
| Django(PyPI) | 3.2.0 | 5.2.17 | cross_major |
| cryptography(PyPI) | 3.2 | 50.0.0 | cross_major |
推奨先にも脆弱性がないかOSVに確認する
推奨は「スキャンで分かった脆弱性(現在の版に該当するもの)」の影響範囲で検証しています。そのため、推奨先に 現在の版には該当しない新しい脆弱性 がありえます。
実際、cryptography 3.2の推奨候補だった49.0.0は、44.0.0で混入し50.0.0で修正された2件の脆弱性に該当していました。v0.8.0からは推奨先をOSVに照会し、該当する脆弱性があればそれも避けて選び直します(この例では50.0.0)。結果は candidate_check に示します。
直接依存か、推移的依存か
脆弱なパッケージが「自分で書いた依存」なのか「何かに引っ張られてきた依存」なのかで、直し方が変わります。OSV-Scannerの出力にはこの区別がないため、lockfileを解析して判定しています。
{
"name": "qs",
"version": "6.7.0",
"dependency_relation": "transitive",
"introduced_by": ["express"]
}
| 形式 | 判定方法 |
|---|---|
package-lock.json |
Nodeの解決規則で依存をたどり、推移的依存には要求元の直接依存(introduced_by)を付ける。workspaceにも対応 |
go.mod |
// indirect の有無。replace で置き換えたモジュールも判定 |
requirements.txt |
ファイルに書かれた依存が直接、deps.devで解決された依存が推移的 |
pom.xml |
OSV-Scannerが宣言された依存と推移的依存を別々に報告するのを利用 |
suggest_fix の update_hint も、この区別に合わせて具体的に案内します。例えばnpmの推移的依存なら「要求している直接依存(express)を更新するか、ルートの package.json の overrides で版を指定する」、Goで replace を使っていれば「require ではなく replace の版を更新する」といった具合です。
yarn.lock・pnpm-lock.yaml・poetry.lock・uv.lockなどは、現在は unknown です。
導入
Node.js 20.19以上が必要です。OSV-Scannerのバイナリは、見つからなければ公式リリースからピン留めした版を自動でダウンロードし、パッケージに埋め込んだSHA-256で検証してから使います。
Claude Codeの場合:
claude mcp add osv-scanner -- npx -y osv-scanner-mcp
Claude Desktop・Codex CLI・VS Code(GitHub Copilot)・Antigravityの設定例はREADMEのSetupにあります。
スキャンできる範囲は、環境変数で制限することをおすすめします(プロンプトインジェクションで意図しないディレクトリをスキャンさせられるのを防ぐため)。
{
"OSV_MCP_ALLOWED_ROOT": "/absolute/path/to/projects"
}
設定後は、例えば次のように依頼できます。
/absolute/path/to/projects/my-appの依存の脆弱性をscan_projectで調べて、スキャンできなかったものがあれば教えてください。
見つかった脆弱性の推奨アップグレードを
suggest_fixで出して、直接依存と推移的依存に分けて対応方法をまとめてください。
通信先について
スキャンではネットワーク照会が発生します。
オフライン完結の検査ではありません。
| 操作 | 通信先 |
|---|---|
| lockfileのスキャン | api.osv.dev |
pom.xml・requirements.txt のスキャン |
api.osv.dev、api.deps.dev(推移的依存の解決) |
suggest_fix の推奨先の確認 |
api.osv.dev |
pom.xml と requirements.txt では、推移的依存を解決するため 依存の名前と版がdeps.devに送られます(社内パッケージの名前を含みます)。
避けたい場合は OSV_MCP_NO_REMOTE_RESOLUTION=1 を設定してください。その代わり推移的依存はスキャンされず、応答にその旨の警告が出ます。
注意点
-
検出0件は安全の保証ではありません。 必ず
coverageと警告を確認してください - lockfileがない依存はスキャンできません。lockfileは信頼できる環境で生成してください
- 推奨は既知の修正版の中から選んでおり、全公開版の中での最小性や、未知の脆弱性がないことは保証しません
- 推奨の例は検証時点のOSVデータに依存し、将来の照会では変わります
まとめ
Java専用だったOSV-Scanner-MCPが、Go・JavaScript・Pythonのプロジェクトにも使えるようになりました。スキャンするだけでなく「どの版に上げればよいか」「直接依存か推移的依存か」まで返すので、MCPクライアントに修正の方針まで相談しやすくなったと思います。
一方で、lockfileがない依存や判定できない形式など、まだ見えない部分もあります。そこを coverage や unknown として隠さずに返すことを重視しています。
不具合や改善案はGitHub Issuesでお知らせください。