Skip to content

エージェント委任

AIエージェントが互いに対話することが増える中 — あるエージェントが別のエージェントを 呼び出してサブタスクを完了する — 新しいクラスのセキュリティリスクが生まれます。 エージェントチェーンは、制限の少ないエージェントを通じてデータをロンダリングし、 分類コントロールを回避するために使用できます。Triggerfishは暗号化されたエージェント アイデンティティ、分類上限、および必須のtaint継承でこれを防ぎます。

エージェント証明書

Triggerfishのすべてのエージェントは、そのアイデンティティ、機能、委任権限を定義する 証明書を持っています。この証明書はエージェントのオーナーによって署名され、エージェント 自身または他のエージェントによって変更できません。

json
{
  "agent_id": "agent_abc123",
  "agent_name": "Sales Assistant",
  "created_at": "2025-01-15T00:00:00Z",
  "expires_at": "2026-01-15T00:00:00Z",

  "owner": {
    "type": "user",
    "id": "user_456",
    "org_id": "org_789"
  },

  "capabilities": {
    "integrations": ["salesforce", "slack", "email"],
    "actions": ["read", "write", "send_message"],
    "max_classification": "CONFIDENTIAL"
  },

  "delegation": {
    "can_invoke_agents": true,
    "can_be_invoked_by": ["agent_def456", "agent_ghi789"],
    "max_delegation_depth": 3
  },

  "signature": "ed25519:xyz..."
}

証明書の主要フィールド:

フィールド目的
max_classification分類上限 — このエージェントが操作できる最高taintレベル。INTERNAL上限を持つエージェントはCONFIDENTIALにtaintされたセッションによって呼び出されることができません。
can_invoke_agentsこのエージェントが他のエージェントを呼び出す権限を持つかどうか。
can_be_invoked_byこのエージェントを呼び出せるエージェントの明示的な許可リスト。
max_delegation_depthエージェント呼び出しチェーンの最大深さ。無制限の再帰を防ぎます。
signatureオーナーからのEd25519署名。証明書の改ざんを防ぎます。

呼び出しフロー

あるエージェントが別のエージェントを呼び出すとき、ポリシーレイヤーは呼び出し先エージェントが 実行する前に委任を確認します。チェックは決定論的でコードで実行されます — 呼び出し元 エージェントは決定に影響できません。

エージェント委任シーケンス: エージェントAがエージェントBを呼び出し、ポリシーレイヤーがtaintと上限を確認し、taintが上限を超えるとブロック

この例では、エージェントAはCONFIDENTIALのセッションtaintを持っています(以前に Salesforceデータにアクセスしたため)。エージェントBはINTERNALの分類上限を持っています。 CONFIDENTIALはINTERNALより高いため、呼び出しはブロックされます。エージェントAの taintされたデータは低い分類上限を持つエージェントに流れることができません。

セキュリティ ポリシーレイヤーは呼び出し元の現在のセッションtaint

チェックします。上限ではありません。エージェントAがCONFIDENTIAL上限を持っていても、 重要なのは呼び出し時のセッションの実際のtaintレベルです。エージェントAが分類された データにアクセスしていない場合(taintがPUBLIC)、問題なくエージェントB(INTERNAL上限) を呼び出せます。 :::

委任チェーン追跡

エージェントが他のエージェントを呼び出すとき、完全なチェーンが各ステップのタイムスタンプと taintレベルで追跡されます:

json
{
  "invocation_id": "inv_123",
  "chain": [
    {
      "agent_id": "agent_abc",
      "agent_name": "Sales Assistant",
      "invoked_at": "2025-01-29T10:00:00Z",
      "taint_at_invocation": "CONFIDENTIAL",
      "task": "Summarize Q4 pipeline"
    },
    {
      "agent_id": "agent_def",
      "agent_name": "Data Analyst",
      "invoked_at": "2025-01-29T10:00:01Z",
      "taint_at_invocation": "CONFIDENTIAL",
      "task": "Calculate win rates"
    }
  ],
  "max_depth_allowed": 3,
  "current_depth": 2
}

このチェーンは監査ログに記録され、コンプライアンスとフォレンジック分析のために クエリできます。どのエージェントが関与し、taintレベルがどうだったか、何のタスクを 実行したかを正確にトレースできます。

セキュリティ不変条件

4つの不変条件がエージェント委任を管理します。すべてはポリシーレイヤーのコードによって 強制され、チェーン内のどのエージェントによっても上書きできません。

不変条件強制
Taintはエスカレートのみ各呼び出し先はmax(自身のtaint, 呼び出し元のtaint)を継承します。呼び出し先は呼び出し元より低いtaintを持つことができません。
上限の遵守呼び出し元のtaintが呼び出し先のmax_classification上限を超える場合、エージェントを呼び出すことができません。
深さ制限の強制チェーンはmax_delegation_depthで終了します。制限が3の場合、4番目レベルの呼び出しはブロックされます。
循環呼び出しのブロック同じチェーンでエージェントは2回現れることができません。エージェントAがエージェントBを呼び出し、エージェントBがエージェントAを呼び出そうとすると、2回目の呼び出しはブロックされます。

taint継承の詳細

エージェントA(taint: CONFIDENTIAL)がエージェントB(上限: CONFIDENTIAL)を正常に 呼び出すと、エージェントBはエージェントAから継承したCONFIDENTIALのtaintで開始します。 エージェントBが次にRESTRICTEDデータにアクセスすると、taintはRESTRICTEDにエスカレート します。この上昇したtaintは呼び出しが完了するとエージェントAに返されます。

taint継承: エージェントA(INTERNAL)がエージェントBを呼び出し、BがtaintをToInheritし、Salesforceにアクセス(CONFIDENTIAL)、Aに上昇したtaintを返す

Taintは両方向に流れます — 呼び出し時に呼び出し元から呼び出し先へ、完了時に呼び出し先から 呼び出し元へ。エスカレートのみ可能です。

データロンダリングの防止

マルチエージェントシステムの主要な攻撃ベクターはデータロンダリング — エージェント チェーンを使用して中間エージェントを通じてルーティングすることで、分類されたデータを より低い分類の宛先に移動することです。

攻撃

攻撃者の目標: PUBLICチャンネルを通じてCONFIDENTIALデータを漏洩

試みられたフロー:
1. エージェントAがSalesforceにアクセス(taint --> CONFIDENTIAL)
2. エージェントAがエージェントBを呼び出す(PUBLICチャンネルを持つ)
3. エージェントBがPUBLICチャンネルにデータを送信

失敗する理由

Triggerfishはこの攻撃を複数のポイントでブロックします:

ブロックポイント1:呼び出しチェック。 エージェントBがCONFIDENTIAL以下の上限を 持っている場合、呼び出しは即座にブロックされます。エージェントAのtaint(CONFIDENTIAL)が エージェントBの上限を超えています。

ブロックポイント2:taint継承。 エージェントBがCONFIDENTIAL上限を持っていて呼び出しが 成功した場合でも、エージェントBはエージェントAのCONFIDENTIAL taintを継承します。 エージェントBがPUBLICチャンネルに出力しようとすると、PRE_OUTPUT hookがライトダウンを ブロックします。

ブロックポイント3:委任でのtaintリセットなし。 委任チェーン内のエージェントはtaintを リセットできません。taintリセットはエンドユーザーのみが利用でき、会話履歴全体をクリアします。 エージェントがチェーン中にtaintレベルを「洗う」メカニズムはありません。

データはエージェント委任を通じて分類を逃れることはできません。上限チェック、

必須のtaint継承、チェーン内でのtaintリセットなしの組み合わせにより、Triggerfishの セキュリティモデル内でエージェントチェーンを通じたデータロンダリングは不可能です。 :::

シナリオ例

シナリオ1:委任の成功

エージェントA(上限: CONFIDENTIAL、現在のtaint: INTERNAL)
  エージェントB(上限: CONFIDENTIAL)を呼び出す

ポリシーチェック:
  - AはBを呼び出せる? YES(BはAの委任リストにある)
  - Aのtaint(INTERNAL)<= Bの上限(CONFIDENTIAL)? YES
  - 深さ制限OK? YES(最大3の深さ1)
  - 循環? NO

結果: 許可
エージェントBはtaint: INTERNALで開始(Aから継承)

シナリオ2:上限によるブロック

エージェントA(上限: RESTRICTED、現在のtaint: CONFIDENTIAL)
  エージェントB(上限: INTERNAL)を呼び出す

ポリシーチェック:
  - Aのtaint(CONFIDENTIAL)<= Bの上限(INTERNAL)? NO

結果: ブロック
理由: エージェントBの上限(INTERNAL)がセッションtaint(CONFIDENTIAL)を下回る

シナリオ3:深さ制限によるブロック

エージェントAがエージェントBを呼び出す(深さ1)
  エージェントBがエージェントCを呼び出す(深さ2)
    エージェントCがエージェントDを呼び出す(深さ3)
      エージェントDがエージェントEを呼び出す(深さ4)

エージェントEのポリシーチェック:
  - 深さ4 > max_delegation_depth(3)

結果: ブロック
理由: 最大委任深さを超えた

シナリオ4:循環参照によるブロック

エージェントAがエージェントBを呼び出す(深さ1)
  エージェントBがエージェントCを呼び出す(深さ2)
    エージェントCがエージェントAを呼び出す(深さ3)

2回目のエージェントA呼び出しのポリシーチェック:
  - エージェントAは既にチェーンに現れている

結果: ブロック
理由: 循環エージェント呼び出しが検出された

関連ページ