本記事は「Confused Deputy: The Old Bug That AI Agents Keep Reintroducing」を翻訳した記事です。
1988年当時、商用タイムシェアリングシステム上で動作するコンパイラは、言語機能の使用統計を記録するために共有ディレクトリに書き込む権限を持っていました。同じディレクトリには、システムの課金記録を保持するファイルも保存されていました。ユーザーはコンパイラに対し、課金ファイルと同じ名前のファイルにデバッグ出力を書き込むよう要求しました。コンパイラはユーザーの権限ではなく自身の権限を使用してファイルを開き、上書きしました。
Norm Hardyは1988年の論文で事件を報告し、Confused Deputy問題と名付けました。正当な権限を持つプログラムが、権限の低いアクターに騙され、アクターの代わりに権限を悪用してしまうシナリオを説明しています。
約40年後、ソフトウェアを構築するほとんどの開発者は、類似の問題に常に遭遇しているにもかかわらず、用語を聞いたことがありません。そして現在、AIエージェントはHardyが想像した以上に広い影響範囲を与えています。
Confused Deputy問題とは何か
メインフレームの文脈はさておき、パターンはシンプルです。代理人(タスクを実行するアプリケーションやサービス)は、呼び出し元が持っていない権限を保持しています。代理人は権限に依存して有用な作業を実行します。途中で、攻撃者は代理人に呼び出し元ではなく攻撃者の利益のために自身の権限を使用させます。
2つの構造的な条件が状況を可能にします。
- 第一に、オブジェクトの参照に使用される識別子(ファイル名、URL、リソースID)自体はアクセス権を持っていません。誰でも
https://example.com/invoices/1234と書き込めますが、リソース名を書き込むことは、開くことを許可されていることと同じではありません。 - 第二に、代理人の権限は自動的に適用され、実際に要求している人物に対して権限を確認する明示的なステップがありません。コンパイラは「特定のユーザーが特定のファイルに対する権限を持っているか」を尋ねませんでした。単に「自分はファイルに対する権限を持っているか」と尋ね、正しい質問に対して間違った答えを得ました。
単一のバグではありません。より高い権限を持つコンポーネントが、より低い権限を持つコンポーネントからの不十分に検証されたリクエストを処理する場合に、権限昇格バグが取り続ける形です。
決してなくならなかった問題
コンパイラの話が学術的に聞こえるとしても、説明されているパターンは今日の運用システムの至る所に存在します。
クロスサイトリクエストフォージェリ(CSRF)は、ブラウザベースの環境で発生するConfused Deputy攻撃です。ブラウザは銀行の有効なセッションCookieを保持しています。悪意のあるページは、ブラウザに銀行の送金エンドポイントへフォームを送信させます。銀行のサーバーは有効なCookieを含むリクエストを確認し、Cookieのみをチェックするため処理します。ブラウザが代理人であり、Cookieが環境権限であり、悪意のあるページは送金権限を持たない攻撃者です。
同じ問題のより一般的なバージョンは、サーバーサイドリクエストフォージェリ(SSRF)に現れます。呼び出し元の代わりにリソースを取得するバックエンドサービスは多数存在します。リンクプレビュー生成器、PDFレンダラー、Webhookリレー、画像プロキシなどです。シナリオでは、呼び出し元がURLを提供し、サービスは自身のネットワーク位置と自身の認証情報を使用して取得します。正当な画像URLの代わりに内部エンドポイントのアドレスを提供する攻撃者は、呼び出し元が直接到達できない場所にサービスを到達させます。エンドポイントが返すシークレットを何でも返します。サービスが代理人であり、ネットワークアクセスが環境権限であり、攻撃者自身はエンドポイントにクエリを実行する権限を持っていませんでした。
AIエージェントが混乱させるのに最適な代理人である理由
AIエージェントは設計上、代理人です。カレンダー、GitHubリポジトリ、課金システムへのアクセス権を与え、すべてのコマンドを自分で入力しなくても代わりに機能するようにします。まさに価値提案の全体です。Hardyが1988年に説明した設定そのものであり、大規模に再現されています。
エージェントを1988年のコンパイラよりも悪化させているのは、指示の受け取り方です。コンパイラには少なくとも、ファイル名パラメータという固定された狭いインターフェースがありました。エージェントはシステムプロンプト、ユーザーリクエスト、検索されたドキュメント、ツールの出力、他のエージェントのメッセージを読み取ります。すべてを同じチャネルを通じて処理します。自然言語はトークン化され、一部のトークンを「信頼できるコマンド」、他のトークンを「信頼できないコンテンツ」としてマークする組み込みの方法を持たないモデルに供給されます。GitHubのIssueタイトルに埋もれた文は、APIキーを所有する人物が入力した文とまったく同じ重みをモデルに対して持ちます。
単一の事実により、Confused Deputyはまれな手作りのエクスプロイトから、攻撃者にとって標準的な手法に近いものに変わります。1988年のコンパイラに権限を悪用させるには、機密ファイルの正確なファイル名を知り、特定のユーザーに要求させる必要がありました。エージェントに権限を悪用させるには、エージェントが読み取る場所(メール、Webページ、コードコメント、サポートチケットなど)に適切な文を配置するだけです。タスク固有の一部ではなく、通常ユーザーの完全なOAuthスコープを保持するエージェントと組み合わせると、混乱しやすく、発生時に危険なほど過剰な権限を持つ代理人が誕生します。
すでに発生している場合
仮説ではありません。2026年2月、幅広いリポジトリアクセスとシェル実行権限を持つ認証済みのGitHub Issueトリアージボットが、細工されたタイトルを持つ新しいIssueを処理しました。タイトルには埋め込み指示が含まれており、エージェントにトリアージワークフロー内で攻撃者が提供したコマンドを実行させました。研究者はターゲットとなったツールにちなんで、手法を「Clinejection」と名付けました。
エージェントの行動は連鎖の終わりではなく、単なる入り口でした。攻撃者は最初の足がかりを利用して、プロジェクトの共有GitHub Actionsキャッシュをジャンクデータで溢れさせました。そして正当なキャッシュエントリを押し出し、別のより権限の高い夜間リリースワークフローで使用されるキーと一致する汚染されたエントリに置き換えました。ワークフローが実行されると、汚染されたキャッシュが復元され、プロジェクトのnpm公開トークンを保持するジョブ内で攻撃者に実行権限が渡されました。トークンを使用して、攻撃者は改ざんされたパッケージバージョンを公開しました。インストールスクリプトは、アップデートをインストールしたすべてのマシンに無関係なAIエージェントツールを密かにダウンロードしました。侵害されたパッケージは、発覚するまでの約8時間の間に約4000回ダウンロードされました。
実際の被害がどこから来たのかを確認します。言語モデルの欠陥からではありません。Issueのタイトルと指示を区別できないエージェントと、信頼できるワークフロー内で実行されるものは定義上信頼できると想定する認証情報およびキャッシュアクセスが組み合わさった結果です。まさにConfused Deputyパターンの全貌です。正当な権限、検証が不十分なリクエスト、そして実際に誰が要求したかを確認せずに代理人の代わりに機能しようとするシステムの連鎖です。
セキュリティ研究者はすでに、MCPツールサーバーの関連パターン(悪意のあるツールの説明が、呼び出し元エージェントが正当として扱う指示を注入できる場合)や、マルチエージェントシステム(あるエージェントが元のリクエストで実際に認可されているかを再検証せずに別のエージェントにタスクを再委任する場合)を追跡しています。パターンは毎回同じです。指示とデータを混在させるチャネルと、そこから到着したものすべてに基づいて行動する代理人です。
古いプレイブックはまだ機能する
Confused Deputy攻撃の修正方法はどれも新しいものではなく、良いニュースです。取得サービスやブラウザセッションを保護するのと同じ原則が、本記事にも直接適用されます。
- 最小特権とは、代理人が実行する可能性のあるすべてのタスクに合わせた継続的な付与ではなく、目の前のタスクに必要な権限のみを代理人に与えることを意味します。
- ケイパビリティベースのセキュリティはさらに進んでいます。解決するために代理人の環境権限に依存する識別子(ファイル名、ユーザーID、URL)の代わりに、オブジェクト参照とアクセス権を束ねたトークンを代理人に渡します。権限は代理人の内部に別々に存在するのではなく、リクエストとともに移動するため、代理人は実際に与えられたことのない権限を悪用するように騙されることはありません。実際には、アクセストークンのオーディエンス、スコープ、権限を確認するだけでなく、きめ細かな認可ツールを使用することを意味します。
- 明示的な権限移譲は、1988年のコンパイラをトラブルに巻き込んだ自動継承を置き換えます。「自分はディレクトリへの書き込みアクセス権を持っているので、処理するすべてのリクエストがアクセス権を得る」のではなく、システムは「特定の呼び出し元が特定のアクションに対して特定の権限を付与した」ことを要求します。さまざまな側面を持つトークン交換は、要件の実装に役立ちます。
代理人がAIエージェントの場合に変わること
プレイブックをエージェントに適用することは、各原則をエージェント固有の障害モードを乗り越えられるものに変換することを意味します。エージェントは何でも信じ込まされる可能性があるため、エージェントの判断が機能しない場合でも認可を維持する必要があります。
エージェントがセッション全体で保持する継続的なOAuthスコープは、コンパイラが共有フォルダに対して持つ包括的な書き込みアクセス権に相当します。タスクをスコープとした短命の認証情報は、最小特権と同じ方法で問題を修正します。エージェントは目の前のタスクに必要なアクセス権を正確に取得し、アクセス権はタスク終了時に期限切れになります。攻撃者が数日後に乗っ取ることができる継続的な付与として持続することはありません。
billing:writeやemail:sendのような広範な動詞も粗すぎます。エージェントがbilling:writeを呼び出せる場合、1回のインジェクション成功で攻撃者は課金関連のあらゆる操作を行えます。ケイパビリティをスコープとした権限は、表面を「50ドル未満の払い戻しを発行する」「スレッドにすでに存在するアドレスにメールを送信する」といった特定のビジネスアクションに狭めます。完全に混乱したエージェントであっても、影響範囲は小さく明確に定義されます。
認証情報自体は、モデルが到達できない場所に存在する必要があります。モデルが「何を渡すべきかを知る」ためにトークンがシステムプロンプトやツールスキーマに配置されている場合、プロンプトインジェクションのペイロードが抽出できるまさにその場所に配置されていることになります。信頼できるパターンは、モデルに何をすべきか(ユーザーのリクエストに基づいてどのツール、どのパラメータか)を決定させ、別の決定論的なコードレイヤーがアクションを実行して認証情報を保持することです。モデルは騙されて漏洩したり悪用したりする可能性のあるトークンを見ることはありません。トークンを持っていないからです。
そして、高価なもの、不可逆的なもの、または重要になるほど広範なものについては、ヒューマンインザループの承認により、エージェントの決定と実際に発生するアクションの間にチェックポイントが設けられます。セッションの開始時に一度だけ与えられる包括的な「はい/いいえ」ではなく、要求された特定のアクションに対する特定の帯域外確認です。
Auth0の適合領域
Auth0 for AI Agentsが構築されているシフトは次のとおりです。エージェントを継続的で広範なスコープの認証情報から遠ざけ、タスクに狭くスコープされ、短命で、使用した特定のエージェントとリクエストまで追跡可能なアクセスへと移行します。定義されたリスクしきい値を超えるものには、人間の承認ステップを利用できます。Token Vaultは、保存して再利用するための継続的な認証情報をエージェントに渡す代わりに、サードパーティAPI用のジャストインタイムトークンを発行します。Auth0のエージェントをファーストクラスのアイデンティティとして扱う取り組みと、タスクの実際の意図に認可をスコープする取り組みはどちらも、本記事で説明してきたギャップを埋めることを直接目指しています。エージェントの判断をより信頼する必要はありません。設計上、信頼を減らす必要があります。
バグはスタックの新しさを気にしない
Confused DeputyはAIが導入した脆弱性クラスではありません。Norm Hardyが1988年に想像できなかった規模でAIエージェントが再導入している脆弱性クラスです。数百万の展開された代理人が存在し、エージェントが最終的に読み取るコンテンツに文を書き込める人なら誰でも到達できます。
修正方法も変わっていません。エージェントの環境アクセスを、特定のリクエストが正当である証拠として扱うのをやめてください。エージェントに渡す各認証情報は、エージェントが責任を持って使用することを期待する包括的な委任ではなく、タスクにスコープされ、タスク終了時に期限切れになる、特定の監査可能なケイパビリティであるべきです。Hardyのコンパイラには、権限の使用方法について選択肢がありませんでした。エージェントにも選択肢を持つ機会を与えるべきではありません。
セキュリティレビュー担当者に説明するのが難しい、エージェントが現在保持している最も広範な継続的権限は何でしょうか。それが最初に絞り込む価値のあるものです。
About the author
Andrea Chiarelli
Principal Developer Advocate
I have over 20 years of experience as a software engineer and technical author. Throughout my career, I've used several programming languages and technologies for the projects I was involved in, ranging from C# to JavaScript, ASP.NET to Node.js, Angular to React, SOAP to REST APIs, etc.
In the last few years, I've been focusing on simplifying the developer experience with Identity and related topics, especially in the .NET ecosystem.
