はじめに
「使っているライブラリに脆弱性がないか調べたい。でもツールの使い方を覚えるのが面倒…」
そんな悩みを解決するために、Claudeに日本語で話しかけるだけでJavaプロジェクトの脆弱性チェックができるツールを作り、npmで公開しました。
あなた「このプロジェクトに脆弱性がないかチェックして」
Claude「スキャンしました。4つのパッケージに14件の既知の脆弱性があります。
最も深刻なのは log4j-core 2.14.1 の Log4Shell(CVE-2021-44228、
CVSSスコア10.0)です。2.25.4 へのアップグレードで
7件すべて解消できます」
こんな会話が実際にできます。この記事では、「何がうれしいのか」「どう使うのか」「中でどう動いているのか」を順番に説明します。
- リポジトリ: https://github.com/tedorigawa001/OSV-Scanner-MCP
- npm: https://www.npmjs.com/package/osv-scanner-mcp
想定読者
- Javaでアプリを作っているが、脆弱性チェックはやったことがない人
- 「MCP」という言葉は聞いたことがあるが、よく分かっていない人
- Claude Code / Claude Desktop を使い始めた人
前提知識を3分で
「依存ライブラリの脆弱性」とは?
最近では、自分でコードを全部書くことはほとんどありません。
ログ出力には log4j、JSON処理には jackson…と、**他人が作ったライブラリ(依存ライブラリ)**を組み合わせます。
問題は、そのライブラリに後から欠陥(脆弱性)が見つかることです。有名な例が2021年の「Log4Shell」。世界中で使われていたログ出力ライブラリ log4j に、「外部から任意のコードを実行できてしまう」という最悪級の脆弱性が見つかり、大騒ぎになりました。
自分のコードが完璧でも、使っているライブラリが古ければ危険——だから「依存ライブラリの脆弱性チェック」が必要なのです。
OSV-Scanner とは?
OSV-Scanner は、Googleが公開している無料の脆弱性スキャナーです。
プロジェクトの依存リスト(Mavenなら pom.xml)を読み取り、OSVという脆弱性データベースと照合して「このライブラリのこのバージョンには、この脆弱性がありますよ」と教えてくれます。
ただし本来はコマンドラインツールなので、コマンドの使い方や大量のJSON出力の読み方を覚える必要があります。
MCP とは?
MCP(Model Context Protocol) は、一言でいうと「AIアシスタントに道具を持たせるための共通規格」です。
Claude のようなAIは、そのままでは「文章を読んで文章を返す」ことしかできません。
そこでMCPサーバーという小さなプログラムを用意して「脆弱性スキャンという道具があるよ」と教えてあげると、Claudeは会話の流れに応じて自分でその道具を使い、結果を読んで、人間の言葉で説明してくれるようになります。
[あなた] ←日本語で会話→ [Claude] ←MCP→ [OSV-Scanner-MCP] → [OSV-Scanner本体]
今回作ったのは、この図の真ん中にいる「通訳係」です。
使ってみる
セットアップ(1コマンド)
Claude Code なら、ターミナルでこれだけです:
claude mcp add osv-scanner -- npx -y osv-scanner-mcp
Claude Desktop の場合は設定ファイル(claude_desktop_config.json)に追記します:
{
"mcpServers": {
"osv-scanner": {
"command": "npx",
"args": ["-y", "osv-scanner-mcp"]
}
}
}
OSV-Scanner本体のインストールは不要です。
初回実行時に公式リリースから自動ダウンロードされます(後述しますが、改ざんされていないかチェックサムで検証してから使います)。
対応プロジェクト
-
Maven:
pom.xmlがあればOK -
Gradle:
gradle.lockfileが必要です。無い場合はツールが生成コマンド(./gradlew dependencies --write-locks)を教えてくれます
会話例
わざと古いライブラリを使ったプロジェクトで試してみます。
ポイントは、どのコマンドをいつ使うかはClaudeが自分で判断することです。ユーザーはコマンドを1つも覚えていません。
提供している3つのツール
| ツール | 役割 |
|---|---|
scan_java_project |
プロジェクトをスキャンし、深刻度順の脆弱性レポートを返す |
suggest_fix |
「どのバージョンに上げるべきか」を提案する |
explain_vulnerability |
CVE/GHSA IDの詳細説明をOSVデータベースから取得する |
explain_vulnerability は地味に重要です。
AIには**知識の期限(カットオフ)**があり、最近公開された脆弱性のことは知りません。
実際、テストしたプロジェクトの14件中5件が2026年採番のCVEで、Claude単体では説明できないものでした。
このツールがあることで、最新の脆弱性でもデータベースから正確な情報を取って説明できます。
作ってみて面白かったポイント
初心者の方にも伝わりそうな話を3つだけ紹介します。
1. バージョン番号の比較は、実は難しい
「2.9.0 と 2.10.0、どっちが新しい?」——人間なら 2.10.0 と即答できますが、文字列として比較すると "2.10.0" < "2.9.0" になってしまいます(1 < 9 なので)。
さらにJavaの世界には 2.17.1-RELEASE のような独特の表記があり、npmで定番のバージョン比較ライブラリ(semver)では正しく扱えません。そこでMaven本家の比較アルゴリズムをTypeScriptに移植し、本家のテストケースをそのまま持ってきて検証しました。「1-ga と 1 は同じ」「1a1 は 1-alpha-1 と同じ」など、知らなかった仕様が山ほど出てきます。
2. 「どのバージョンに上げるべきか」は単純ではない
Log4Shellの修正版を調べると 2.12.2、2.15.0、2.25.4…と複数のバージョンが並んでいます。これは表記ゆれではなく、「2.12系を使い続けたい人向けの修正版」「最新系の修正版」のように、系統ごとにパッチが出ているからです。
単純に最大値を勧めると、2.12系を使っている人にいきなりメジャーアップグレードを迫ることになります。そこで「①今と同じ系統の修正版 → ②同じメジャー内 → ③メジャーアップグレード」の順で探す3段階フォールバックを実装しました。破壊的変更のリスクが最も小さい提案を優先する、実務目線の工夫です。
3. セキュリティツール自身が攻撃経路にならないように
面白い(そして怖い)のがここです。MCPサーバーへの入力は「AIが組み立てた値」なので、信用してはいけません。プロンプトインジェクション(AIを騙して変な指示を実行させる攻撃)を経由して、悪意ある値が届く可能性があるからです。
- パスに
../../etcを混ぜられても大丈夫なように、実体パスに解決してから境界チェック - コマンドはシェルを経由せず、引数も固定リストのみ(
; rm -rf /のような注入が構造的に不可能) - 自動ダウンロードするバイナリは、公式リリースのSHA256チェックサムをソースコードに埋め込んで照合。検証に合格するまで実行権限を与えない
- Gradleの「ビルド実行方式」は
build.gradleの任意コード実行を伴うため、あえて不採用(lockfile方式のみ)
「脆弱性を調べるツールが脆弱」では笑えないので、ここは最初から丁寧に作りました。
ハマったポイント(開発小話)
- OSV-Scannerの終了コード: 脆弱性が見つかると exit code 1 で終わります(エラーではなく正常)。さらに「依存ゼロのpom.xml」は128。ドキュメントより実機確認が確実でした
- CVE-IDで検索すると404になることがある: OSVデータベースの正式IDはGHSA形式で、CVE-IDは解決できない場合があります。404時に「GHSA-IDで照会してね」と案内するようにしました
-
公開直後の
npxが command not found: 原因は途中で中断した初回実行が残した壊れたnpxキャッシュ。rm -rf ~/.npm/_npxで解決。パッケージを疑う前にキャッシュを疑いましょう
まとめ
- AIに道具を持たせる(MCP)と、専門ツールが「会話するだけ」で使えるようになる
- セットアップは
claude mcp add osv-scanner -- npx -y osv-scanner-mcpの1行 - 中身は「入力を信用しない」を徹底したTypeScript製ラッパー(Apache-2.0で公開中)
脆弱性チェックは「意識が高い人がやる特別なこと」ではなく、歯磨きのような習慣になるべきものです。会話するだけでできるなら、その第一歩のハードルはかなり下がるはず。ぜひ試してみてください。
