← すべての記事
AI とエージェント IT / CIO 公開済み · · 著者 ObjectStack Team

MCP セキュリティ:プロトコルだけではなぜ足りないのか

MCP と A2A は agent とツールの接続を簡単にする。だが接続は認可ではない。企業に必要なのは、呼び出しごとに身元、権限、監査を強制するツール層だ。

MCP セキュリティ:プロトコルだけではなぜ足りないのか
  • MCP
  • A2A
  • Agent 相互運用
  • ツール層
  • AI ガバナンス
  • トレンド

結論から言うと: 接続のプロトコル(MCP、A2A)はもう決着がついている。企業になお欠けているのは、その背後にある層――身分を運び、権限を強制し、呼び出しのたびに監査の痕跡を残し、しかもあなたが手書きしなくてよい、ガバナンスされたツール層だ。

ある会社のエンジニアが、一日の午後をかけて本番データベースに MCP サーバーの層を一枚かぶせ、社内の agent を「つないだ」。デモはスムーズで、上司も満足した。

翌日、ある営業が agent に何気なく尋ねた。「全顧客の契約金額を一覧表にエクスポートして。全体感を見たいんだ。」

agent は喜んでそのとおりにした――全社分を、一件残らず、この営業がそもそも閲覧権限を持たない他のエリアや、他人の名義の契約まで含めて。悪意はなく、ただ とても親切 だっただけだ。問題は、あの午後に急ごしらえした包装に 身分という概念がなかった ことだ――それは、尋ねたのが誰で、その人がもともとどのデータを見られるのかを知らない。それが agent に晒したのは、このサービスが触れられるすべてだった。

この一覧表は、のちに数十人のグループに転送された。誰かがおかしいと気づき、セキュリティチームが介入したときには、損失はすでに発生していた――ハッカー攻撃のようなドラマチックな損失ではなく、もっと収拾のつきにくい種類のものだ。社内の給与等級、顧客の商務条件、同僚の業績が、一度に、「役に立とう」という名目のもとで、見るべきでない人に漏れた。事後、誰が何を見たのかを誰もはっきり言えなかった――それらの呼び出しは どの監査帳簿にも入っていなかった からだ。

この一件が起きたのは、まさに「接続」というものが、今あまりに簡単になったからだ。

接続の戦いは、ほぼ終わった――それこそがリスクの在り処だ

まずこの大きな事実を認めよう。MCP と A2A は、主要な AI プラットフォームやクラウド、開発者ツールの会話に入り、agent が「どうツールにつなぐか、どう別の agent につなぐか」を標準化しつつある。

だが成功そのものが罠を生んだ。接続という作業が突然、数時間で片づくようになった。すると、本当に難しく、本当に重要な部分――つないだあと、やっていいことか、やったら記帳するか――が、とりわけ「あとで足す」こととしてついで扱いで省かれやすくなる。冒頭のあの午後は、こうして生まれた。

ここで一つの類比を借りる価値があるが、借りるのは一度だけだ。MCP は TCP/IP に似ていて、「パケットをどう相手に届けるか」を標準化した。だが本番システムを裸の TCP の上に直接架ける者はいない――その上にはさらに TLS が生え、身分が生え、「誰が何をできるか、どんな証拠を残すか」が生えなければならない。agent エコシステムは今、まさに「TCP/IP を敷き終えたばかり」の瞬間で止まっている。賑わいは本物だが、その上の層はまだ生えていない。

自分で認可を足し、安全なツールだけを晒す――それでいいのでは?

責任あるチームはこう反論するだろう。あの午後は手抜きをしただけで、我々はそんなことはしない――各 MCP サーバーに自分で認可を足し、審査を経た安全なツールだけを晒すから、と。

これは正しいが、二つのことを過小評価している。

第一に、それはスケールしない。 一つや二つのサーバーなら丁寧に認可を足せるが、企業はすぐに数十のサーバー、数百のツールになり、その一つひとつに身分の検証、権限の判定、監査の記帳を手書きしなければならない――これ自体が、誰も読まないグルーコードの大きな塊で、まさに「技術的負債」の記事で語ったあの負債だ。ただ今回はツール層に生えている。

第二に、「我々は気をつける」はアーキテクチャではない。 それは、人が常に間違えず、駆け込まず、近道をしないことを当てにした約束だ。そして我々は皆知っている。締め切りが来れば、「まずつないで、認可はあとで足す」という道が、いつだって最も歩きやすい道だ。あるセキュリティ属性が、全員が毎回自覚的であることに頼らねばならないなら、それは遅かれ早かれ破れる――冒頭のあの会社のエンジニアも、セキュリティを知らなかったわけではない。ただ時間に追われていただけだ。

本当の解は「もっと丁寧に手書きする」ことではなく、「身分を帯び、権限を帯び、痕跡を残す」ことをツールの デフォルトの姿 にすること――省けず、毎回手書きする必要もない、というものだ。

裸のインターフェースをツールに包むのは、スーパーユーザーの通行証を一枚発行するに等しい

なぜ裸のインターフェースが agent にとってこれほど危険なのか? 包まれたインターフェースが、もともと信頼できるバックエンドサービスのために設計されたものであって、自分で判断する agent のために設計されたものではない からだ。それらは呼び出し側がすでに認可済みであることを前提とし、だから自分ではあまり身分を検証しない。それを直接 MCP ツールとして晒すと――

  • agent が手にするのは 身分のない インターフェースだ――それは「この営業の身分で照会する」のではなく、サービスの権限ですべてを照会する。
  • その書き込み操作は サービスの権限 で算定され、起動者のものではないため、間違っても責任を帰属できない。
  • これらの呼び出しは どの業務監査帳簿にも入らず、事後に調べようがない(冒頭のあの漏洩は、まさにこの一点で行き詰まった)。

ひとことに言えば――裸のインターフェースを MCP ツールに包むのは、agent にスーパーユーザーの通行証を一枚発行するに等しい。

欠けているその層:呼び出しのたびに身分、権限、痕跡を帯びる

プロトコルの上に本当に足すべきは、ガバナンスされたツール層だ――agent が呼ぶのは裸のインターフェースではなく、呼び出しのたびに人とまったく同じ関門をくぐる一組の制御された動作だ。

ガバナンスされたツール呼び出しのライフサイクル:ユーザーの身分で起動し、ランタイムが権限を検証し、制御下で実行し、監査に書き込む

裸のインターフェースのやり方は、間の三ステップを丸ごと省くことで、そして省かれるのがちょうど「やっていいことか」と「記帳するか」だ。ここで最も見落とされやすいのが第一ステップ――身分の伝播 だ。agent は起動者(あの営業)の身分で呼び出さなければならず、サービス自身の身分でではない。いったん身分が正しくなれば、「彼は自分のエリアの契約しか見られない」がランタイムの強制できる事実になり、モデルが守ってくれることを願うだけの提案ではなくなる。

agent が別の agent を呼び始めるとき:身分はどう伝えていくか

身分の伝播という問題は、A2A(agent が agent を呼ぶ)が普及したあと、より深刻になり、最も穴が開きやすくなる。

想像してみよう。営業が「営業アシスタント agent」に「この顧客の更新資料を準備して」と言う。この agent は自分だけでは片づかないので、「財務 agent」を呼んで支払いサイクルを取り、「契約 agent」を呼んで過去の条件を取りにいく。さて、ここで問題だ――財務 agent が実行するとき、使われるのは の権限か? もしチェーンの途中のどこか一跳びで身分が失われ、「財務 agent サービス自身の権限」で照会する形になれば、この営業は一連の agent リレーを介して、本来見る権限のない財務を見てしまう。越権は最初の一跳びで起きるのではなく、ひそかに二跳び目、三跳び目で起きる。

裸のインターフェース式の接続では、この「身分がチェーンの中で蒸発する」がほぼデフォルトの結果で、しかも統一された監査帳簿がないため、事後にこのリレーで結局誰が何を見たのかを復元することが、まったくできない。ガバナンスされたツール層が正しくやるべきは、起動者の身分を A2A チェーン全体に沿ってずっと伝えていく ことだ――どの一跳びでも、最初のあの人の権限で検証され、記帳される。プロトコル(A2A)が agent をつなぐ役を担うが、「リレーの過程で権限が失われず、痕跡が途切れない」ことは、プロトコルの背後のあのガバナンス層に保証してもらうしかない。

あなたのツール層が健全かどうか、五つの問いで調べられる

  1. agent がツールを呼ぶとき、帯びているのは 起動者の身分 か、サービスの身分か?
  2. 一度の越権呼び出しは、ランタイムに その場で阻止 されるか、それともモデルが「自覚的にやらない」ことに頼るか?
  3. ツール呼び出しのたびに、監査帳簿 に入っているか?
  4. agent が agent を呼ぶとき、最初のあの人の身分は 伝わっていく か?
  5. 権限を一つ変えると、一か所で効く か、それとも各サーバーに行って一つずつ変えるのか?

ツールは一つずつ手書きすべきではなく、定義から生えてくるべきだ

では、どうすれば手書きせず、かつデフォルトで安全にできるのか? 答えはこうだ。ツールを業務定義から 自動で生やす。あなたはオブジェクトと権限を宣言する――たとえば、あるカスタマーサポートの返金シナリオ。

export const Refund = ObjectSchema.create({
  name: 'support_refund',
  fields: { amount: Field.currency({ label: '返金額', min: 0 }) },
});

export const AgentRole: Security.PermissionSet = {
  name: 'support_agent',
  objects: {
    support_refund: { allowRead: true, allowCreate: true, allowEdit: false, allowDelete: false },
  },
};

ランタイム(ObjectOS)は 自動で それを、agent が呼び出せる一組のガバナンスされたツールへと投影する。照会、返金の作成、そのそれぞれに上の権限の検証が組み込まれ、ログインユーザーの身分で実行され、統一された監査帳簿に落ちる。「返金が上限超過なら承認を経る」はオブジェクトにぶら下がったフローで、ツールがそれに該当すると自動で一時停止してサインを待つ――これらをツールのコードの中に手書きする必要はない。権限を一つ変えれば、関係するすべてのツールが一か所で効く。

危険なバージョンと照らし合わせれば、違いははっきりする。

// 裸のツール:リスクを直接モデルの「自覚」に委ねる
{ "name": "run_sql", "description": "任意の SQL クエリを実行する", "params": { "sql": "string" } }

あなたはツールごとに権限コードを書くのではなく、ただ権限を宣言する。ツールは定義の投影だ。MCP が「どうつなぐか」を担い、この層が「つないだあと、やっていいことか、記帳するか」を担う――しかも手書きしなくてよい。

まず冷や水を:それが管理するのは「できるか」であって「すべきか」ではない

ここで一本の境界線を引いておかなければならない。さもないと、それを神格化しやすい。

ガバナンスされたツール層が制約するのは 被害範囲 であって、判断力 ではない。それは agent が権限を持たないことをできないように保証できる――これは重要で、冒頭のあの漏洩はそれにその場で阻止されただろう。だがそれは 「権限の範囲内だが、とても愚かな」動作を止められない。もしカスタマーサポート agent がもともと返金を起動する権限を持っていて、返金すべきでない一件を返金したら、ツール層は通常どおり通す――それが権限の範囲内だからだ。

言い換えれば、それが解決するのは「越権」と「無痕跡」であって、「判断が正しいかどうか」は解決しない。後者はやはり評価に頼り、高リスクの動作を人の承認に留めることに頼り、フローの設計に頼るしかない。誰かがあなたに「ガバナンスされたツール層につなげば、agent は絶対安全だ」と言うなら、それは誇張だ。それは必要な土台であって、建物のすべてではない――だがこの土台がなければ、冒頭のあの漏洩は何度も繰り返し起きる。

結び

MCP を TCP/IP にたとえるのは間違っていない。だが忘れてはならない。インターネットの価値ある部分は、TCP/IP の上にあの身分と説明責任の層が生えてきたあとに初めて生まれたものだ。

agent エコシステムは、まさに同じ瞬間にいる。接続はすでに標準化され、冒頭のあの「役に立とうとした午後」はますます増えていく――つなぐのがあまりに簡単だからだ。そして A2A が agent をチェーンにつなげれば、ガバナンスのない接続は越権をさらに深く隠すだけだ。今後一〜二年で本当に希少で、本当に価値があるのは、また一つの接続プロトコルではなく、プロトコルの背後にある、権限を強制し、チェーンに沿って身分を保ち、痕跡を残し、しかも手書きしなくてよいツール層だ。それはすべてを解決しないが、それがなければ、残りのすべてが本番に載せられない。

npm i -g @objectstack/cli && os start

オブジェクトとその権限を一つ宣言し、agent にツールを通じて、変更権限のないデータを越権で変えさせてみよう――ランタイムがどうやってその場で阻止し、この試みも帳簿に記録するかを見てほしい。