MCPサーバーは安全か|RCE事例と選定チェックリスト2026
公式のファイル操作用MCPサーバーを1本入れた。付いてきた依存パッケージは133個。npm auditを走らせると、high(重大度: 高)が4件返ってきた。しかも「No fix available」。
これは仮の話ではない。2026年7月、手元のLinux環境(Node v22.22.2 / npm 10.9.7)で実際に叩いた結果だ。Anthropicが配布している一次パッケージ、バージョンは@modelcontextprotocol/[email protected]。特別に古いものでも、怪しい野良サーバーでもない。
MCPサーバーの総数は2026年7月16日時点で22,311件に達した。2026年4月時点の公開サーバー1万件超から、3か月で倍増している。増えたのは選択肢だけではない。攻撃面も同じ速度で広がった。
この記事の要点
- 公式サーバーでも依存133個・high 4件。危険なのは「怪しいサーバー」だけではない
- パストラバーサル対策は正しく効いていた。破綻したのは許可ディレクトリを1階層広げた瞬間
- 2026-07-28仕様でMCPサーバーは純粋なリソースサーバーになり、トークン窃取系の攻撃は仕様レベルで塞がれる
公式サーバー1本で依存133個という現実
MCPサーバーのリスクは、コードの中身より先に依存ツリーの大きさに現れる。実際に計測した結果は133パッケージ・high 4件。数字は素っ気ない。
$ npm install @modelcontextprotocol/server-filesystem
npm warn deprecated [email protected]: Old versions of glob are not supported,
and contain widely publicized security vulnerabilities
added 133 packages in 6s
$ npm audit
# npm audit report
brace-expansion <=5.0.7
Severity: high
brace-expansion: DoS via unbounded expansion length causing an
out-of-memory process crash - GHSA-mh99-v99m-4gvg
No fix available
4 high severity vulnerabilities
high 4件は全部1本のチェーンから来ている
4件と聞くと4か所に穴があるように見えるが、実態は違う。すべて単一の依存チェーンが数え上げられた結果だ。
| 階層 | パッケージ | 状態 |
|---|---|---|
| 根本 | brace-expansion <=5.0.7 | GHSA-mh99-v99m-4gvg(DoS / メモリ枯渇でプロセス停止) |
| ↑依存 | minimatch 2.0.0 - 10.0.2 | 脆弱なbrace-expansionに依存 |
| ↑依存 | [email protected] | deprecated警告つき |
| ↑依存 | [email protected] | 公式パッケージ本体 |
深刻度はDoSどまり。コード実行ではない。ファイル検索に使うglob展開へ極端に長いパターンを渡されるとメモリを食い潰して落ちる、という筋の話だ。MCPサーバーは手元で動かすプロセスなので、いきなり情報が抜かれるわけでもない。
ただ、気になるのは深刻度そのものではない。
「No fix available」が示しているもの
npm auditは修正版を案内しなかった。返ってきたのは「Some issues need review, and may require choosing a different dependency」という一文だ。上流に直したバージョンが無い。つまり、使う側にできることは実質ない。
一次配布元のパッケージが、deprecated警告の出るライブラリを掴んだまま出荷されている。MCPサーバーを選ぶとき、多くの人はツールの機能や対応クライアントを見る。依存ツリーを見る人は少ない。ここは見落としがちだ。実際に監査を通して出てきたhigh 4件は、すべて自作コードではなく他人のコード側から来ていた。
導入前に30秒でできること
入れる前にnpm view <パッケージ名> dependenciesとnpm auditを通すだけで、依存の規模と既知の穴が分かる。MCPサーバーおすすめ2026で紹介しているような定番サーバーでも、この2コマンドは省略しないほうがいい。
2026年、MCPの脆弱性は散発から連続に変わった
2026年1〜2月の2か月だけで、MCP関連のCVEは30件を超えた(Practical DevSecOps集計)。Vulnerable MCP Projectの分類では登録50件超のうち13件がCritical。もはや個別事故ではなく、傾向として見るべき数字になっている。
押さえておきたい主要CVE
| CVE | 対象 | 内容 |
|---|---|---|
| CVE-2025-49596 CVSS 9.4 |
MCP Inspector(公式デバッグツール) | DNSリバインディング経由のRCE。Oligo Securityが報告 |
| CVE-2026-0755 CVSS 9.8 |
gemini-mcp-tool | 未認証のコマンドインジェクションからRCE |
| CVE-2026-30623 | LiteLLM | stdio経由の認証済みRCE。JSON設定で任意コマンドを指定できた |
| CVE-2025-58444 | MCP Inspector | XSSからRCEへのエスカレーション |
| CVE-2026-35394 | Mobile MCP | Android intent経由のRCE |
並べて見ると偏りが分かる。上位2件はCVSS 9点台、つまり最も危険な帯。そして公式のデバッグツールであるMCP Inspectorが2件を占めている。「野良サーバーを避ければ安全」という直感は、この時点で崩れる。
stdioトランスポートの構造的な弱さ
個別のCVEより重いのが、OX Securityが2026年4月に報告したstdioトランスポートの設計レベルの欠陥だ。Python・TypeScript・Java・Rustの全実装に共通する問題として扱われ、個別のCVE番号は振られていない。実装ミスではなく設計側の話だからだ。
stdioは、MCPサーバーをローカルの子プロセスとして起動し標準入出力で会話する方式だ。手軽さと引き換えに、設定ファイルへ書いたコマンド文字列がそのまま実行される。ここが弱い。LiteLLMのCVE-2026-30623が典型で、JSON設定に任意のコマンドと引数を書ける状態だった。設定ファイルを書き換えられる=コードを実行できる、とほぼ同義になる。
許可ディレクトリはどこまで守ってくれるか、試した
結論から言う。公式filesystemサーバーのパストラバーサル対策は、正しく効いていた。
手順はシンプルだ。/tmp/mcpsec/sandboxだけを許可して起動し、その外にダミーの機密ファイル(outside_secret.txt)を置く。JSON-RPCを直接流し込んで検証した3件の結果が、下記になる。
$ npx -y @modelcontextprotocol/server-filesystem /tmp/mcpsec/sandbox
Secure MCP Filesystem Server running on stdio
Client does not support MCP Roots, using allowed directories
set from server args: [ '/tmp/mcpsec/sandbox' ]
# (a) 許可内
-> read_text_file /tmp/mcpsec/sandbox/ok.txt
<- "safe content"
# (b) 許可外を直接指定
-> read_text_file /tmp/mcpsec/outside_secret.txt
<- isError: true
"Access denied - path outside allowed directories"
# (c) 相対パスで脱出を試みる
-> read_text_file /tmp/mcpsec/sandbox/../outside_secret.txt
<- isError: true
"Access denied - path outside allowed directories"
(c)が重要だ。../で親に登る古典的なパストラバーサルは、パスを正規化したうえで弾かれている。エラーメッセージも正規化後の絶対パスを表示していて、実装として素直だ。MCPサーバーを自作するなら、ここは真似する価値がある。
見逃せない起動ログが1行あった
「Client does not support MCP Roots, using allowed directories set from server args」。MCP Rootsはクライアント側から作業範囲を宣言する仕組みだが、クライアントが未対応だと起動引数のパスにフォールバックする。
許可範囲を最終的に決めるのは、設定ファイルに書いた引数1個だ。クライアントが守ってくれると思っていると、前提を取り違える。
1階層広げただけで、同じファイルが読めた
同じサーバー、同じリクエスト。変えたのは起動時の許可パスを/tmp/mcpsec/sandboxから親の/tmp/mcpsecにした一点だけだ。
$ npx -y @modelcontextprotocol/server-filesystem /tmp/mcpsec
-> read_text_file /tmp/mcpsec/outside_secret.txt
<- isError: undefined
"SECRET_KEY=sk-live-example"
さっきまでAccess deniedを返していた同一ファイルが、中身をそのまま返してきた。攻撃も回避テクニックも使っていない。設定を一段ゆるくしただけだ。それで全部通る。
正直、予想していたのに手が止まった。引数1個の差でCVE 5件分より大きな穴が開く。脆弱性リストを追う前に、自分のclaude_desktop_config.jsonのパスを見直すほうが早い。
効いていたのは実装、壊したのは設定
CVEを潰しても、許可パスにホームディレクトリや/を書いた瞬間に全部無意味になる。.env・.ssh・ブラウザのプロファイルは、たいていホーム直下にある。
既定で14ツール、うち4つが書き込み系
サーバーを繋ぐと、何が生えるのか。tools/listを叩いて計測した結果は14件。想像より多い。
読み取り系(10個)
read_file / read_text_file / read_media_file / read_multiple_files / list_directory / list_directory_with_sizes / directory_tree / search_files / get_file_info / list_allowed_directories
書き込み系(4個)
write_file / edit_file / create_directory / move_file
読むだけの用途でも、既定で書き換えと移動ができる状態で繋がる
読み取り専用オプションは用意されていない
「参照だけさせたい」という用途は多い。ところが公式filesystemサーバーに読み取り専用フラグは無く、書き込み系ツールを外す手段も無い。分離したければ、読ませたいファイルだけをコピーした専用ディレクトリを作って、そこを許可するのが現実的な落としどころになる。
ツール定義そのものが攻撃面になる
もう一つ、MCP特有の面倒さがある。ツールの説明文はLLMがそのまま読む。悪意ある説明文に指示を埋め込む「ツール汚染」や、後からアップデートで説明文を差し替える「ラグプル」が成立するのはそのためだ。
通常のライブラリなら、更新時に差分を読めば気づける。MCPサーバーの説明文はコードレビューの対象になりにくく、そのうえAIエージェントが自律的に読む。人間の目が入らない経路で指示が届く、という構図になる。
2026-07-28仕様で認証の責任分界が固定された
2026年7月28日に正式リリースされたMCP公式仕様は、認証まわりの前提を書き換えた。MCPサーバーは認可機能を一切持たない純粋なリソースサーバーとして再定義され、認証・同意・トークンの発行と失効は専用の認可サーバーへ完全に委譲される。
これまでは「認証は各サーバー実装者にお任せ」だった。トークン窃取系のCVEが並んだ背景はそこにある。MCP 2026-07-28仕様の変更点のうち、セキュリティに直結するのは次の3本のRFC必須化だ。
| RFC | 実装側 | 防げるようになる攻撃 |
|---|---|---|
| RFC 9728 Protected Resource Metadata |
サーバー | クライアントが正しい認可サーバーを自動発見できる。偽の認可先へ誘導する手口を潰す |
| RFC 8707 Resource Indicators |
クライアント | トークンの宛先サーバーを明示。悪意あるサーバーが別サーバー宛トークンを騙し取る攻撃を防ぐ |
| RFC 9207 Issuer Identification |
クライアント | 認可レスポンスのiss検証を必須化し、mix-up攻撃を防止 |
ステートレス化はセキュリティにも効く
同じ仕様でsessionsとinitializeハンドシェイクが削除された。狙いはスケーラビリティ(ラウンドロビンLBの背後に置ける)だが、副次的な効果として、セッション固定やセッションストア汚染といった状態管理由来の攻撃面が丸ごと消える。持たない状態は、漏れない。
非推奨機能には最低12か月の猶予がある。とはいえ新しいクライアントには即座に影響する。自作サーバーを公開しているなら、移行は年単位ではなく月単位で考えるべき局面だ。
導入前チェックリスト
ここまでの検証とCVE 5件から、手を動かす順番でまとめる。上から順に潰せば、事故率の高いところから落ちていく。
STEP 1|入れる前
- 配布元が一次か(GitHub organizationを確認)
npm auditを通す- 依存数を見る。100超なら理由を疑う
- 最終更新が3か月以内か
STEP 2|設定するとき
- 許可パスは使うディレクトリだけ
- ホーム直下と
/は指定しない - APIキーは設定ファイルに直書きしない
- stdioの起動コマンドを目視する
STEP 3|運用中
抜けるのはここだ。
- 更新時にツール説明文の差分を見る
- 使っていないサーバーは外す
- 書き込み系ツールの要否を再確認
- 2026-07-28仕様への対応状況を追う
許可パスの書き方(悪い例と良い例)
// NG: ホーム全体を渡している
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem",
"/home/user"]
}
}
}
// OK: 作業対象のプロジェクトだけに絞る
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem",
"/home/user/projects/blog-site"]
}
}
}
たったこれだけの差で、~/.ssh/id_rsaが読めるかどうかが決まる。ワンクリック導入の便利さと引き換えに、この引数を確認しないまま使い始めるケースは多い。
クラウド系サーバーは権限設計が本体
ローカルのファイル操作と違い、AWS MCPサーバーのようなクラウド連携型は、渡すIAMロールの範囲がそのまま被害範囲になる。読み取り専用ポリシーで足りるなら、書き込み権限を渡す理由はない。最小権限は原則論ではなく、単純に事故ったときの損害額の話だ。
今日やるなら、この1つ
設定ファイルを開いて、filesystem系サーバーの引数パスを1行確認する。ホーム直下を指していたら、作業対象のプロジェクトのパスへ書き換える。所要2分。CVEを1件追いかけるより効く。
よくある質問
公式サーバーだけ使えば安全ですか
いいえ。CVSS 9.4のCVE-2025-49596と、XSS起点のCVE-2025-58444は、どちらも公式のMCP Inspectorで見つかっている。今回の依存133個・high 4件も公式パッケージの実測値だ。一次配布かどうかは判断材料の1つでしかない。
npm auditでhighが出たら使うのをやめるべき?
中身次第。今回のGHSA-mh99-v99m-4gvgはDoSで、ローカル実行のMCPサーバーなら実害は限定的だ。コード実行や情報漏洩に繋がる種類なら話が変わる。深刻度のラベルではなく、攻撃が成立する条件を読むこと。
パストラバーサルは結局防げているんですよね?
公式filesystemサーバーでは防げていた。../での脱出は正規化後に拒否される。ただし守備範囲は「許可ディレクトリの外」であって、許可ディレクトリの中身は全部読める。範囲の指定を誤れば対策は機能しない。
2026-07-28仕様に今すぐ移行すべきですか
サーバーを公開しているなら早いほうがいい。非推奨機能の猶予は12か月あるが、RFC 9728への対応は認証まわりの作り直しを伴うので着手が遅いほど重くなる。個人利用でクライアント側だけなら、対応版のリリースを待てば足りる。
使うサーバーは何本くらいまでが妥当ですか
本数の上限より、1本あたり14個前後のツールが生えることを意識したほうがいい。5本繋げば70個。LLMが選択を誤る確率も、汚染された説明文を踏む確率も上がる。繋いだ5本のうち、週1回以上使うものだけ残すのが現実的だ。
まとめ
MCPサーバーの危険は、野良パッケージを掴むことではない。公式の一次配布でも依存は133個付いてきて、監査はhigh 4件を「修正版なし」で返す。それが2026年7月時点の標準的な出発点だ。
一方で、実装側の守りは思ったより堅かった。パストラバーサルは正規化して弾かれる。壊れたのは許可パスを1階層広げた瞬間で、同じファイルが平然と返ってきた。守りを無効化したのは攻撃ではなく設定だった。
仕組みから整理し直したいならMCPとは何かの解説を先に読んでおくと、権限まわりの判断が早くなる。仕様側も2026-07-28版でMCPサーバーを純粋なリソースサーバーへ寄せ、トークン窃取系の攻撃を仕様レベルで塞ぎにきた。前提は良くなっていく。
それでも許可範囲を決めるのは、最後まで設定を書く人間だ。だから優先順位はこうなる。CVE一覧を追う前に、自分の設定ファイルの引数を1行直す。