MCP.so
ログイン
ブログに戻る

MCP セキュリティのベストプラクティス:脅威・対策・チェックリスト

2026年10月15日MCP.so TeamMCP.so Team

MCP 公式仕様に基づくセキュリティのベストプラクティス。プロンプトインジェクション、ツールポイズニング、Confused Deputy、トークンパススルー、SSRF、ローカルサーバーへの対策とチェックリストを解説します。

MCP セキュリティのベストプラクティスを一言で

MCP セキュリティのベストプラクティスは、3 つのルールに集約できます。サーバーが送ってくるもの(ツールの説明、ツールの結果、OAuth の URL)はすべて信頼できない入力として扱うこと、各サーバーとトークンに与える権限を最小限にすること、そして書き込み・送信・削除を伴う操作には必ず人間の確認を挟むことです。公式の MCP Security Best Practices ページと 認可仕様(現行リビジョン 2026-07-28)は、これらのルールを具体的な MUST / SHOULD 要件に落とし込んでいます。本記事では各脅威を、サーバー作者・クライアント利用者・組織それぞれの対策に対応づけ、最後にチェックリストをまとめます。

脅威マップの全体像

脅威何が起きるか最初に対処すべき人
ツール出力経由のプロンプトインジェクションツールが返した Web ページ、issue、メールに、モデルが従ってしまう指示が含まれるクライアントと利用者
ツールポイズニングとラグプルツールの説明に隠し指示が仕込まれる、または承認済みのツールが後から変更されるクライアントと組織
Confused Deputy静的な OAuth クライアント ID を使う MCP プロキシにより、攻撃者が同意画面を回避できるサーバー作者
トークンパススルーサーバーが自分宛てに発行されていないトークンを受け入れたり転送したりするサーバー作者
広すぎるスコープ盗まれたトークン 1 つで全ツールが使えてしまうサーバー作者と認可サーバー
悪意あるローカルサーバーワンクリックインストールで任意のコマンドがマシン上で実行されるクライアント、利用者、組織
OAuth ディスカバリー中の SSRF悪意あるサーバーがクライアントを内部 URL に誘導するクライアント作者
ステートハンドルの乗っ取り推測されたカート ID やワークフロー ID から他ユーザーのデータが漏れるサーバー作者

後半の 6 行は仕様のセキュリティページから直接引いたものです。最初の 2 行はプロトコルのバグではありません。だからこそ危険です。これらはワイヤーフォーマットではなく、モデルそのものを突く攻撃だからです。

ツール出力経由のプロンプトインジェクション

ツールの結果はすべて最終的にモデルのコンテキストに入ります。ツールが GitHub の issue、Web ページ、受信トレイを取得すれば、そのコンテンツを書いた人はモデルを操ろうとすることができます。たとえば、プライベートリポジトリを読ませて、その内容を公開の場所に投稿させる、といった具合です。Invariant Labs は 2025 年に、GitHub MCP 連携を使うエージェントに対してまさにこのパターンを実証しました。

仕様の tools セクション は双方の責任を明記しています。

  • サーバーはすべてのツール入力を検証し、アクセス制御を実装し、呼び出しをレート制限し、ツール出力をサニタイズしなければなりません(MUST)。
  • クライアントは機密性の高い操作に確認を求め、サーバーを呼び出す前にツール入力をユーザーに見せ、ツール結果をモデルに渡す前に検証し、タイムアウトを設定し、ツールの使用をログに記録すべきです(SHOULD)。
  • 信頼と安全のため、ツール呼び出しを拒否できる人間が常にループ内にいるべきです(SHOULD)。

実践的な対策は次のとおりです。

  • 読み取り用と書き込み用のサーバーを分ける。 信頼できないコンテンツ(ブラウジング、issue、メール)を読むエージェントには、同じセッション内でコードのプッシュやメール送信ができるトークンを持たせないでください。
  • 副作用のある操作は確認をオンのままに。 読み取り専用ツールの自動承認は問題ありませんが、書き込み、削除、支払い、外部へのメッセージ送信は確認プロンプトの後ろに置きましょう。
  • トークンを 1 つのリポジトリやワークスペースに限定する。 GitHub MCP Server が 1 つのリポジトリしか見えなければ、注入された指示は他のリポジトリに届きません。
  • ブラウザ系ツールには注意する。 Playwright MCP Server は任意のページを読み込むため、必要がない限りログイン状態を含まないプロファイルで実行してください。

ツールポイズニング、シャドーイング、ラグプル

ツールの説明は、モデルは読むがユーザーは通常目にしないプロンプトテキストです。Invariant Labs の 2025 年 4 月の公開情報 では、3 つの亜種が説明されています。

  • ツールポイズニング: add 関数のような無害に見えるツールに、SSH 鍵や設定ファイルを読み取り、パラメーター経由でこっそり持ち出す指示が隠されている。
  • シャドーイング: 悪意あるサーバーの説明が、別の信頼できるサーバーのツールの使われ方を変えてしまう。たとえばメールの宛先を密かに書き換える。
  • ラグプル: すでに承認したサーバーが、後からツール定義を変更する。

仕様自体の立場として、クライアントはツールのアノテーション(読み取り専用や破壊的操作のヒントなど)を、信頼できるサーバーからのものでない限り信頼できないものとして扱わなければなりません(MUST)。対策は次のとおりです。

  • 説明を全文表示する。 クライアントは短縮ラベルではなく、モデルが実際に見ている内容を表示すべきです。
  • バージョンを固定し、定義をハッシュで管理する。 設定でパッケージのバージョンを固定し(@latest ではなく npx -y some-server@1.4.2)、ツール定義のハッシュが変わったら再レビューします。
  • サーバーごとにツールの名前空間を分ける。 仕様では、複数サーバーを集約するクライアントは、名前が衝突するツールをサーバー接頭辞などで区別すべきだとしています(SHOULD)。
  • インストールを減らす。 接続中のサーバーはそれぞれモデルのコンテキストにテキストを追加します。使っていないサーバーは切断しましょう。

Confused Deputy(MCP プロキシサーバー)

これは、1 つの静的な OAuth クライアント ID でサードパーティ API を仲介しつつ、MCP クライアントの動的登録を許可する MCP サーバーを作る場合に該当します。攻撃者は自分の redirect_uri でクライアントを登録し、被害者にリンクを送ります。サードパーティの認可サーバーは既存の同意 Cookie を見て同意画面をスキップし、認可コードが攻撃者のサーバーに届いてしまいます。

仕様は MCP プロキシサーバーに対し、サードパーティ認可サーバーへ転送する前にクライアントごとの同意を実装することを求めています。

  • ユーザーごとに承認済み client_id の台帳を保持し、最初にそれを確認する。
  • MCP サーバー自身の同意ページを表示し、クライアント名、サードパーティのスコープ、正確な redirect_uri を示す。CSRF 対策と frame-ancestors または X-Frame-Options: DENY も必須。
  • 同意 Cookie は __Host- プレフィックス、Secure、HttpOnly、SameSite=Lax を使い、署名し、特定の client_id に紐づけなければならない(MUST)。
  • redirect_uri は完全一致の文字列比較で検証する。
  • 使い捨てで有効期限の短い state 値を生成し、同意が承認された後にのみ保存する。

トークンパススルーとオーディエンス検証

トークンパススルーとは、サーバーがクライアントのトークンを自分宛てに発行されたものか確認せずに受け入れ、下流に転送することです。仕様はこれを明確に禁止しています。MCP サーバーは、自分宛てに明示的に発行されていないトークンを一切受け入れてはなりません(MUST NOT)。これはレート制限や監査証跡を壊し、盗まれた 1 つのトークンを複数サービスへの通行証に変えてしまいます。

サーバー作者向け:

  • すべてのトークンのオーディエンス(aud クレームまたはイントロスペクション結果)を、自サーバーの正規 URI と照合する。
  • 上流 API を呼ぶ場合は、別個の上流トークンを取得する。クライアントのトークンは決して転送しない。
  • 明示的にマルチテナントでない限り、単一の issuer またはテナントに固定する。

トークンを 1 つのサーバーに紐づけるリソースインジケーターを含む全体の流れは、MCP 認証と OAuth ガイド で解説しています。

広すぎるスコープ

最初から files:*、db:*、admin:* を付与されたトークンは、ログから漏れたときの影響範囲が非常に大きくなります。仕様のスコープ最小化ガイダンスは次のとおりです。

  • 低リスクの読み取り操作だけをカバーする mcp:tools-basic のような最小スコープから始める。
  • 特権ツールが初めて使われたときに、狙いを絞った WWW-Authenticate チャレンジ(error="insufficient_scope" 付きの 403)で追加のスコープを求める。
  • *、all、full-access のようなワイルドカードや包括的なスコープは避け、scopes_supported にあらゆるスコープを列挙しない。
  • 権限はツールごとにサーバー側でチェックする。スコープのクレームだけでは認可ロジックになりません。

利用者にとっても API キーで同じ考え方が当てはまります。サーバーごとにキーを作成し、ワークフローに読み取りだけが必要なら読み取り専用にしましょう。

悪意ある、または侵害されたローカルサーバー

ローカル(stdio)サーバーは、あなたのユーザー権限で動くプログラムです。仕様に挙げられている悪意ある起動コマンドの例には、~/.ssh/id_rsa をリモート URL に送信するものも含まれています。クライアントがローカルサーバーのワンクリックインストールに対応している場合、省略のない正確なコマンドを表示し、それがコード実行であることを明示し、ユーザーの明示的な承認を求めなければなりません(MUST)。クライアントは危険なパターン(sudo、rm -rf、ネットワーク呼び出し)を強調表示し、最小限のデフォルト権限でサンドボックス内でサーバーを実行すべきです(SHOULD)。

今日からできること:

  • 承認前にコマンドを読む。 既知の公開元のサーバーを優先し、mcp.so の掲載を含め、あらゆる掲載情報の背後にあるリポジトリを確認しましょう。
  • ファイルシステムの範囲を絞る。 Filesystem MCP Server は許可するディレクトリを引数で受け取ります。プロジェクトフォルダーを渡し、ホームディレクトリは決して渡さないでください。
  • コンテナ化する。 Docker MCP Gateway などでサーバーをコンテナ内で動かせば、侵害されたサーバーが触れられる範囲を制限できます。
  • サーバー作者へ: ローカルサーバーには stdio を優先してください。どうしてもローカルで HTTP を待ち受ける場合は、認可トークンを必須にするか Unix ドメインソケットを使ってください。DNS リバインディングにより、保護されていない localhost ポートに到達できてしまうからです。

SSRF と悪意ある OAuth URL

OAuth ディスカバリーの間、クライアントはサーバーが制御する URL を取得します。resource_metadata の URL、authorization_servers のリスト、認可サーバーメタデータ内の各エンドポイントです。悪意あるサーバーはこれらを 169.254.169.254(クラウドメタデータ)、localhost:6379、プライベートアドレス帯に向けることができます。クライアント作者は HTTPS を必須にし(開発時のループバックのみ http を許可)、プライベートおよびリンクローカルの IP 帯をブロックし、リダイレクトのホップごとに検証し、エグレスプロキシの利用を検討すべきです(SHOULD)。仕様は、8 進数・16 進数・IPv4 射影 IPv6 といったエンコードのトリックがあるため、IP の解析を自前で実装しないよう警告しています。

認可 URL そのものも入力です。クライアントは http と https スキームのみを許可し、javascript:、data:、file: を拒否しなければならず(MUST)、cmd.exe や sh などのシェル経由で URL を開いてはなりません(MUST NOT)。

ステートハンドルとミックスアップ攻撃

2026-07-28 リビジョンはステートレスです。プロトコルレベルのセッションはないため、状態を保持する必要があるサーバーはハンドル(カート ID、ワークフロー ID)を発行し、ツールの引数として受け取ります。サーバーはハンドルを持っていることを認証とみなしてはなりません(MUST NOT)。ハンドルは安全な乱数生成器で生成し、有効期限を設け、検証済みトークンから得たユーザー ID に紐づけてください。複数の認可サーバーとやり取りするクライアントは、期待される issuer を記録し、認可コードを交換する前に認可レスポンスの iss パラメーター(RFC 9207)を検証しなければなりません(MUST)。これにより、PKCE だけでは防げないミックスアップ攻撃を阻止できます。

MCP セキュリティチェックリスト

サーバー作者

  • すべてのツール入出力を検証・サニタイズし、ツール呼び出しをレート制限する。
  • リモート HTTP サーバーでは仕様どおりに OAuth を実装し、自分宛てでないトークンは決して受け入れず転送もしない。
  • 最小スコープと段階的な権限昇格チャレンジを設計し、ツールごとに認可を強制する。
  • プロキシ:クライアントごとの同意、redirect_uri の完全一致、使い捨ての state。
  • 推測不能でユーザーに紐づいたステートハンドルを使い、ハンドルで認証しない。
  • ツールの説明は短く正直に保ち、モデルへの指示を含めない。変更は目に見える形でバージョン管理する。

クライアント利用者

  • 既知の公開元からサーバーをインストールし、バージョンを固定し、起動コマンドを読む。
  • API キーと OAuth の許可は最小範囲に限定し、サーバーごとに 1 つのキーを使う。
  • 書き込み、削除、外部へのメッセージ送信には確認をオンのままにする。
  • 可能であれば、信頼できないコンテンツを扱うツールと高権限ツールを同じセッションで混在させない。
  • 使わなくなったサーバーは切断し、設定ファイルに貼り付けたキーはローテーションする。

組織

  • 承認済みサーバーとバージョンの許可リストを管理し、ツール定義の変更をレビューする。
  • ローカルサーバーはファイルシステムとネットワークへのアクセスを制限したコンテナやサンドボックスで実行する。
  • 認証情報はシークレットマネージャーに保管し、コミットされる設定ファイルではなく環境変数として注入する。
  • ツール呼び出しを一元的にログ記録し、異常な量や宛先にアラートを出す。
  • 展開前に MCP Inspector でサーバーをテストし、チームが使う クライアント が OAuth に対応しているか確認する。

次のステップ

まずはすでに使っているサーバーから始めましょう。各サーバーの認証情報がどこにあり、どんなスコープを持ち、書き込みに確認が必要かを確かめてください。そのうえで MCP サーバーディレクトリ から公式または公開元がメンテナンスする代替を探し、リモートサーバーを構築するなら MCP 認証の仕組み を読んでください。

よくある質問

MCP は安全ですか?

プロトコル自体はリモートサーバー向けの OAuth 2.1、トークンのオーディエンス検証、ユーザーの同意といったセキュリティ要件を定めていますが、安全性は実装次第です。実際のリスクの多くは信頼できないサーバー、ツール出力経由のプロンプトインジェクション、権限過剰なトークンから生じるため、サーバーを精査し、機密性の高い操作は人間が承認するようにしましょう。

MCP のツールポイズニングとは何ですか?

ツールポイズニングとは、悪意ある MCP サーバーが、モデルは読むがユーザーは通常目にしないツールの説明に指示を隠す攻撃です。関連するラグプルは承認済みのサーバーが後からツール定義を変更するもので、バージョンを固定し、定義が変わったら再レビューすることが対策になります。

MCP のトークンパススルーとは何ですか?

トークンパススルーとは、MCP サーバーが自分宛てに発行されていないトークンを受け入れ、下流の API に転送してしまうアンチパターンです。MCP 仕様はこれを禁止しており、サーバーはトークンが自分宛てに発行されたことを検証し、上流 API には別のトークンを取得する必要があります。

ローカルの stdio MCP サーバーを実行しても安全ですか?

ローカルの stdio サーバーはあなたのユーザー権限で動くため、安全性は承認したコードとコマンド次第です。既知の公開元からインストールし、正確な起動コマンドを読み、バージョンを固定し、ファイルとネットワークへのアクセスを制限したコンテナやサンドボックスで実行してください。