0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OSV-Scanner-MCP v0.11.0: Java専用からGo・JavaScript・Pythonへ拡張してみた

0
Posted at

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 のような正規形でない表記も正規化します。PyPA packaging と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でお知らせください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?