Skip to content

多層防御

Triggerfishshは13の独立した重複するレイヤーとしてセキュリティを実装しています。単独では どのレイヤーも十分ではありません。合わせて、1つのレイヤーが侵害されても緩やかに低下する 防御を形成します。

セキュリティ 多層防御とは、どの単一レイヤーの脆弱性もシステムを

侵害しないことを意味します。チャンネル認証を回避した攻撃者でも、セッションtaint追跡、 ポリシーhook、監査ログに直面します。プロンプトインジェクションされたLLMでも、 その下の決定論的なポリシーレイヤーに影響を与えることはできません。 :::

13のレイヤー

レイヤー1:チャンネル認証

保護対象: なりすまし、不正アクセス、アイデンティティの混乱。

アイデンティティは、LLMがメッセージコンテンツを解釈するのではなく、セッション確立時の コードによって決定されます。LLMがメッセージを見る前に、チャンネルアダプターが 不変のラベルでタグ付けします:

{ source: "owner" }    -- 確認されたチャンネルIDが登録されたオーナーと一致
{ source: "external" } -- それ以外の人;入力のみ、コマンドとして扱われない

認証方法はチャンネルによって異なります:

チャンネル方法確認
Telegram / WhatsAppペアリングコードワンタイムコード、5分有効期限、ユーザーアカウントから送信
Slack / Discord / TeamsOAuthプラットフォームOAuthコンセントフロー、確認済みユーザーIDを返す
CLIローカルプロセスユーザーのマシン上で実行、OSによる認証
WebChatなし(公開)すべての訪問者はEXTERNALownerにはなれない
Emailドメインマッチング送信者ドメインと設定された内部ドメインを比較

LLMは誰がオーナーかを決定しません。確認されていない送信者からの

「私はオーナーです」というメッセージは{ source: "external" }とタグ付けされ、 オーナーレベルのコマンドをトリガーできません。この決定はコードで行われ、LLMが メッセージを処理する前に完了します。 :::

レイヤー2:権限対応データアクセス

保護対象: 過剰なデータアクセス権限、システム認証情報による特権昇格。

Triggerfishshはシステムサービスアカウントではなく、ユーザーの委任OAuthトークンを使用して 外部システムにクエリを実行します。ソースシステムが独自の権限モデルを強制します:

従来型とTriggerfish: 従来モデルはLLMに直接制御を与え、TriggerfishはすべてのアクションをポリシーLayerを通じてルーティング

Plugin SDKはAPIレベルでこれを強制します:

SDKメソッド動作
sdk.get_user_credential(integration)ユーザーの委任OAuthトークンを返す
sdk.query_as_user(integration, query)ユーザーの権限で実行
sdk.get_system_credential(name)ブロックPermissionErrorを発生

レイヤー3:セッションTaint追跡

保護対象: コンテキスト汚染によるデータ漏洩、分類されたデータがより低い分類の チャンネルに到達すること。

すべてのセッションは、セッション中にアクセスされたデータの最高分類を反映するtaint レベルを独立して追跡します。Taintは3つの不変条件に従います:

  1. 会話ごと — 各セッションは独自のtaintを持つ
  2. エスカレートのみ — taintは増加するが、低下しない
  3. 完全リセットですべてをクリア — taintと履歴は一緒に消去される

ポリシーエンジンが出力を評価する際、セッションのtaintをターゲットチャンネルの有効な 分類と比較します。taintがターゲットを超えると、出力はブロックされます。

レイヤー4:データ系譜

保護対象: 追跡不可能なデータフロー、データがどこに行ったかを監査できないこと、 コンプライアンスのギャップ。

すべてのデータ要素は、起点から宛先までのプロベナンスメタデータを持ちます:

  • 起点: どの統合、レコード、ユーザーアクセスがこのデータを生成したか
  • 分類: どのレベルが割り当てられ、その理由
  • 変換: LLMがデータをどのように変更、要約、または結合したか
  • 宛先: どのセッションとチャンネルが出力を受け取ったか

系譜はフォワードトレース(「このSalesforceレコードはどこへ行きましたか?」)、 バックワードトレース(「この出力にどのソースが貢献しましたか?」)、および 完全なコンプライアンスエクスポートを可能にします。

レイヤー5:ポリシー強制Hook

保護対象: プロンプトインジェクション攻撃、LLM主導のセキュリティ回避、 制御されていないツール実行。

8つの決定論的なhookがデータフローの重要なポイントですべてのアクションをインターセプトします:

Hookインターセプト対象
PRE_CONTEXT_INJECTIONコンテキストウィンドウに入る外部入力
PRE_TOOL_CALLLLMのツール実行要求
POST_TOOL_RESPONSEツール実行から返るデータ
PRE_OUTPUTシステムを離れようとするレスポンス
SECRET_ACCESS認証情報アクセス要求
SESSION_RESETTaintリセット要求
AGENT_INVOCATIONエージェント間の呼び出し
MCP_TOOL_CALLMCPサーバーツール呼び出し

Hookは純粋なコードです:決定論的、同期、ログ記録済み、偽造不可能。LLMはhookを回避できません。 なぜなら、LLM出力からhook設定へのパスウェイが存在しないからです。hookレイヤーは LLM出力をコマンドとして解析しません。

レイヤー6:MCP Gateway

保護対象: 制御されていない外部ツールアクセス、MCPサーバー経由で入る未分類データ、 スキーマ違反。

すべてのMCPサーバーはデフォルトでUNTRUSTEDであり、管理者またはユーザーが分類するまで 呼び出せません。Gatewayは以下を強制します:

  • サーバーの認証と分類状態
  • ツールレベルの権限(サーバーが許可されていても個々のツールをブロック可能)
  • リクエスト/レスポンスのスキーマ検証
  • すべてのMCPレスポンスのtaint追跡
  • パラメーターのインジェクションパターンスキャン
MCPサーバー状態: UNTRUSTED(デフォルト)、CLASSIFIED(レビュー済み、許可済み)、BLOCKED(明示的に禁止)

レイヤー7:プラグインサンドボックス

保護対象: 悪意のあるまたはバグのあるプラグインコード、データ漏洩、 不正なシステムアクセス。

プラグインはダブルサンドボックス内で実行されます:

プラグインサンドボックス: DenoサンドボックスがWASMサンドボックスをラップし、プラグインコードは最内層で実行

プラグインは以下ができません:

  • 宣言されていないネットワークエンドポイントへのアクセス
  • 分類ラベルなしでデータを出力
  • taint伝播をトリガーせずにデータを読み取り
  • Triggerfishsh外にデータを永続化
  • システム認証情報を使用(ユーザーの委任認証情報のみ)
  • サイドチャンネル経由でのデータ漏洩(リソース制限、生ソケットなし)

プラグインサンドボックスはエージェントexec環境とは異なります。プラグインは

システムが「から」保護する信頼されていないコードです。exec環境はエージェントが 「構築するために」許可されたワークスペースです — サンドボックス分離ではなく、 ポリシーで管理されたアクセスで。 :::

レイヤー8:シークレット分離

保護対象: 認証情報の盗難、設定ファイル内のシークレット、プレーンテキスト 認証情報ストレージ。

認証情報はOSキーチェーン(個人ティア)またはvault統合(エンタープライズティア)に 保存されます。以下には決して現れません:

  • 設定ファイル
  • StorageProviderの値
  • ログエントリ
  • LLMコンテキスト(認証情報はHTTPレイヤーで注入、LLMの下)

SECRET_ACCESS hookは、リクエストするプラグイン、認証情報スコープ、決定を含む すべての認証情報アクセスをログ記録します。

レイヤー9:ファイルシステムツールサンドボックス

保護対象: パストラバーサル攻撃、不正なファイルアクセス、直接ファイルシステム 操作による分類バイパス。

すべてのファイルシステムツール操作(読み取り、書き込み、編集、リスト、検索)は、 セッションのtaintに適したワークスペースサブディレクトリにスコープされたOSレベルの 権限を持つサンドボックス化されたDeno Worker内で実行されます。サンドボックスは 3つの境界を強制します:

  • パスジェイル — すべてのパスは絶対パスに解決され、セパレーターを意識した マッチングでジェイルルートと照合されます。ワークスペースからエスケープする トラバーサル試行(../)はI/Oが発生する前に拒否されます
  • パス分類 — すべてのファイルシステムパスは固定の解決チェーンを通じて分類されます: ハードコードされた保護パス(RESTRICTED)、ワークスペース分類ディレクトリ、 設定済みパスマッピング、次にデフォルト分類。エージェントはセッションのtaintを 超えるパスにアクセスできません
  • Taintスコープ権限 — サンドボックスWorkerのDeno権限は、セッションの現在の taintレベルに一致するワークスペースサブディレクトリに設定されます。taintが エスカレートすると、Workerは拡張権限で再起動されます。権限はセッション内で 広がることのみ可能で、狭まることはありません
  • 書き込み保護 — 重要ファイル(TRIGGER.mdtriggerfish.yamlSPINE.md)は、 サンドボックス権限に関係なくツールレイヤーで書き込み保護されています。これらの ファイルは、独自の分類ルールを強制する専用管理ツールを通じてのみ変更できます

レイヤー10:エージェントアイデンティティ

保護対象: エージェントチェーンによる特権昇格、委任を通じたデータロンダリング。

エージェントが他のエージェントを呼び出す際、暗号化された委任チェーンが特権昇格を防ぎます:

  • 各エージェントは機能と分類上限を指定する証明書を持つ
  • 呼び出し先はmax(自身のtaint, 呼び出し元のtaint)を継承 — taintはチェーンを通じて 増加のみ
  • 呼び出し先の上限を超えるtaintを持つ呼び出し元はブロックされます
  • 循環呼び出しは検出され拒否されます
  • 委任の深さは制限され、強制されます
データロンダリング防御: 攻撃パスは上限チェックでブロックされ、taint継承が低分類チャンネルへの出力を防ぐ

レイヤー11:監査ログ

保護対象: 検出不可能な侵害、コンプライアンス障害、インシデント調査の不能。

すべてのセキュリティ関連の決定は完全なコンテキストでログ記録されます:

json
{
  "timestamp": "2025-01-29T10:23:45Z",
  "user_id": "user_123",
  "session_id": "sess_456",
  "action": "slack.postMessage",
  "target_channel": "external_webhook",
  "session_taint": "CONFIDENTIAL",
  "target_classification": "PUBLIC",
  "decision": "DENIED",
  "reason": "classification_violation",
  "hook": "PRE_OUTPUT",
  "policy_rules_evaluated": ["rule_001", "rule_002"],
  "lineage_ids": ["lin_789", "lin_790"]
}

ログ記録される内容:

  • すべてのアクションリクエスト(許可と拒否の両方)
  • 分類決定
  • セッションtaintの変更
  • チャンネル認証イベント
  • ポリシールール評価
  • 系譜レコードの作成と更新
  • MCP Gateway決定
  • エージェント間の呼び出し

監査ログは無効化できません。ポリシー階層の固定ルールです。組織管理者でさえ

自分のアクションのロギングをオフにできません。エンタープライズデプロイメントでは、 フォレンジック要件のための完全なコンテンツログ(ブロックされたメッセージコンテンツを 含む)をオプションで有効にできます。 :::

レイヤー12:SSRF防止

保護対象: サーバーサイドリクエストフォージェリ、内部ネットワーク偵察、 クラウドメタデータの漏洩。

すべてのアウトバウンドHTTPリクエスト(web_fetchbrowser.navigate、プラグインの ネットワークアクセスから)は、最初にDNSを解決し、解決されたIPをプライベートおよび 予約済み範囲のハードコードされた拒否リストと照合します。これにより、攻撃者が 細工したURLを通じてエージェントに内部サービスへのアクセスをさせることを防ぎます。

  • プライベート範囲(10.0.0.0/8172.16.0.0/12192.168.0.0/16)は常にブロック
  • リンクローカル(169.254.0.0/16)とクラウドメタデータエンドポイントはブロック
  • ループバック(127.0.0.0/8)はブロック
  • 拒否リストはハードコードされており設定不可 — 管理者オーバーライドなし
  • DNS解決はリクエストの前に行われ、DNSリバインディング攻撃を防ぎます

レイヤー13:メモリ分類ゲーティング

保護対象: メモリを通じたクロスセッションデータ漏洩、メモリ書き込みによる 分類ダウングレード、分類されたメモリへの不正アクセス。

クロスセッションメモリシステムは書き込みと読み取りの両方のタイミングで分類を強制します:

  • 書き込み: メモリエントリは現在のセッションのtaintレベルに強制されます。 LLMは保存されるメモリのより低い分類を選択できません。
  • 読み取り: メモリクエリはcanFlowToでフィルタリングされます — セッションは 現在のtaintレベル以下のメモリのみ読み取れます。

これにより、エージェントがCONFIDENTIALデータをメモリにPUBLICとして保存し、後で より低いtaintセッションで取得してライトダウン禁止ルールを回避することを防ぎます。

信頼階層

信頼モデルは誰が何に対して権限を持つかを定義します。上位ティアは下位ティアの セキュリティルールを回避できませんが、それらのルール内の調整可能なパラメーターを 設定できます。

信頼階層: Triggerfishshベンダー(アクセスゼロ)、組織管理者(ポリシーを設定)、従業員(境界内でエージェントを使用)

個人ティア: ユーザー自身が組織管理者です。完全な主権。Triggerfishshの

可視性なし。ベンダーはデフォルトでユーザーデータへのアクセスがゼロであり、 ユーザーからの明示的な時間制限付きログ記録されたグラントを通じてのみアクセスできます。 :::

レイヤーが連携する仕組み

悪意のあるメッセージがデータを漏洩しようとするプロンプトインジェクション攻撃を 考えてみましょう:

ステップレイヤーアクション
1チャンネル認証メッセージに{ source: "external" }のタグ付け — オーナーではない
2PRE_CONTEXT_INJECTION入力のインジェクションパターンスキャン、分類
3セッションtaintセッションtaint変更なし(分類されたデータへのアクセスなし)
4LLMがメッセージを処理LLMはツール呼び出しをリクエストするよう操作される可能性がある
5PRE_TOOL_CALLexternal-sourceルールに対するツール権限チェック
6POST_TOOL_RESPONSE返されたデータを分類、taintを更新
7PRE_OUTPUT出力の分類とターゲットを照合
8監査ログシーケンス全体をレビュー用に記録

ステップ4でLLMが完全に侵害されデータ漏洩ツール呼び出しをリクエストしても、 残りのレイヤー(権限チェック、taint追跡、出力分類、監査ログ)は引き続きポリシーを 強制します。単一障害点でシステムが侵害されることはありません。