たきびAIラボ TAKIBI · AI · LAB
💻AI開発 ハウツー 公開 2026.05.13

LLMエージェントの「過剰権限」を排除する

OWASP LLM06:2025 準拠の最小権限設計チェックリスト

OWASP LLM06:2025「Excessive Agency」が定義する3次元リスク(機能・権限・自律性)を整理し、ツール権限スコープ絞り込み・認可委譲・Human-in-the-Loop設計・監査ログの実装チェックリストを提供する。

読了 約13分
LLMエージェントの「過剰権限」を排除する:OWASP LLM06:2025 準拠の最小権限設計チェックリスト

AIエージェントに「なんでもできる権限」を渡していないだろうか。メールの読み書き、ファイルシステムへのアクセス、外部APIの呼び出し——機能を詰め込むほど便利になる一方で、エージェントが誤動作したとき、あるいはプロンプトインジェクション攻撃を受けたときの被害は権限の広さに比例して拡大する。

この問題をOWASPは**LLM06:2025「Excessive Agency(過剰な主体性)」**として定義している。本記事では、このリスクを3つの次元で整理し、実装レベルで使えるチェックリストと設計パターンを解説する。

Excessive Agency とは何か:3次元で理解する

OWASPのLLM Top 10 2025によれば、Excessive Agencyは単に「権限が広すぎる」という話ではない。リスクは次の3つの次元から生まれる。

次元1:過剰な機能(Excessive Functionality)

エージェントに接続されているツールやプラグインが多すぎる状態。開発中に追加したデバッグ用ツール、将来のために「念のため」付けておいたAPIコネクタ、使われなくなった統合機能——これらが残り続けることで、LLMが予期しない方法でそれらを呼び出すリスクが生まれる。

典型例: カスタマーサポートチャットボットに、問い合わせ対応とは無関係なコード実行ツールが接続されたままになっている。

次元2:過剰な権限(Excessive Permissions)

ツールやAPIに付与された権限が、実際に必要なスコープより広い状態。「読み取りだけでいい処理」に書き込み権限が付いている、「1つのテーブルだけアクセスすればいい」のにDB全体にアクセスできる、といったケースが該当する。

典型例: 予約確認メールを送信するエージェントが、メールボックス全体の読み取り・削除権限を持っている。

次元3:過剰な自律性(Excessive Autonomy)

人間の承認なしに不可逆的・破壊的な操作を実行できる状態。これは機能や権限が適切でも問題になる。エージェントが「良かれと思って」ファイルを削除したり、メールを一括送信したりするケースがこれに当たる。

典型例: 「古いファイルを整理して」という指示で、バックアップフォルダを丸ごと削除した。


リスクシナリオ:実際に何が起きるか

シナリオ1:ツールの誤用による意図しないデータ書き込み

社内ドキュメント検索エージェントに、検索用の読み取りAPIと一緒に「ドキュメント更新API」も接続されていた。プロンプトインジェクションを仕込んだ悪意あるドキュメントを検索した際に、エージェントが更新APIを呼び出して別のドキュメントを書き換えてしまった。

根本原因: 検索処理に書き込み権限は不要だが、開発時の利便性のために付けたまま残っていた。

シナリオ2:過剰なファイルシステムアクセス

コード生成エージェントに、プロジェクトのワーキングディレクトリへのアクセスとして/home/user/全体の読み書き権限が付与されていた。エージェントが環境変数ファイル(.env)や SSH 秘密鍵を読み取り可能な状態になっていた。

根本原因: サンドボックスなしでホームディレクトリ全体をマウントしていた。

シナリオ3:外部API呼び出しの無制限化によるレート制限・コスト爆発

コスト最適化の調査を行うエージェントに、クラウドプロバイダーのAPI(レート制限なし)が接続されていた。エージェントが大量のAPIコールを繰り返した結果、予期しない高額請求が発生し、かつサービスの利用制限に引っかかった。

根本原因: ツールレベルでの呼び出し回数制限・タイムアウト設定がなかった。


最小権限設計の実装チェックリスト

以下のチェックリストは、開発フェーズで判断が必要な意思決定ポイントを整理したものだ。チームのレビューや設計段階での確認に使ってほしい。

ツール・プラグイン管理

  • エージェントに接続するツールの一覧を明示的に管理している
  • 現在のタスクスコープで実際に使用するツールのみを接続している
  • 開発・デバッグ用ツールは本番環境から除外されている
  • ツール一覧を定期的にレビューし、不要なものを削除する運用がある

権限スコープ設計

  • 各ツール・APIには必要最小限のスコープのみを付与している
  • 読み取りだけで済む処理に書き込み権限を付与していない
  • ファイルアクセスはサンドボックスまたは特定ディレクトリに限定されている
  • データベースアクセスは必要なテーブル・カラムに限定されている
  • 外部APIにはレート制限・タイムアウト・コスト上限を設定している

呼び出し元ユーザーコンテキストへの認可委譲

  • エージェントは呼び出し元ユーザーの権限を超えた操作を実行できない
  • エージェント用の共有サービスアカウントではなく、実行コンテキストに応じたスコープで認可している
  • ユーザーがアクセス権を持たないリソースにエージェントがアクセスできない構成になっている

Human-in-the-Loop(詳細は次セクション)

  • 不可逆的な操作(削除、送信、課金発生)は人間の確認を必須にしている
  • 高リスク操作のリストを定義・文書化している
  • 自動実行を許可する操作の範囲を明示的に定義している

監査ログ(詳細は後述)

  • すべてのツール呼び出しをログに記録している
  • ログには操作内容・結果・呼び出し元ユーザーを含めている
  • ログは改ざん不可能なストレージに保存されている

Human-in-the-Loop 承認フローの設計パターン

「エージェントにすべて自動処理させる」と「すべてに人間の確認を挟む」の間には、実務的なバランスが必要だ。以下の設計パターンを参考にしてほしい。

パターン1:リスク分類による承認ゲート

操作をリスクレベルで3段階に分類し、レベルに応じた承認要件を設定する。

リスクレベル操作の例承認要件
Lowデータ読み取り、検索、計算自動実行可
Mediumデータ書き込み、通知送信ログ記録 + 事後通知
High削除、課金発生、外部公開事前に人間の確認必須

パターン2:影響範囲による動的エスカレーション

操作の影響が一定の閾値を超えたとき自動的に承認要求を出す。

def check_approval_required(operation: dict) -> bool:
    """操作が人間の承認を必要とするか判定する"""
    
    # 削除操作は常に承認必要
    if operation["type"] == "delete":
        return True
    
    # 影響ファイル数が閾値を超えたら承認必要
    if operation.get("affected_files", 0) > 10:
        return True
    
    # メール送信先が一定数を超えたら承認必要
    if operation["type"] == "send_email" and len(operation.get("recipients", [])) > 5:
        return True
    
    # コスト推定が閾値を超えたら承認必要
    if operation.get("estimated_cost_usd", 0) > 1.0:
        return True
    
    return False

パターン3:承認フローの実装例(簡略化)

# エージェント設定例(概念的なYAML)
agent:
  tools:
    - name: file_write
      approval_required: true
      approval_timeout_seconds: 300
      fallback_on_timeout: "abort"  # タイムアウト時は中断

    - name: send_email
      approval_required: true
      approval_conditions:
        - recipients_count_gt: 1
        - contains_attachment: true

    - name: search_documents
      approval_required: false
      rate_limit:
        calls_per_minute: 10

承認フローで重要なのは、タイムアウト時の挙動を明示的に定義することだ。デフォルトで「中断」か「続行」かを決めず放置すると、実装によってはタイムアウト後に自動続行してしまう。


実務での使い方

既存エージェントの権限監査

すでに稼働しているエージェントがある場合、まず「何のツールが接続されているか」を棚卸しするところから始める。

【権限監査プロンプト例】
このAIエージェントの設定を見て、以下を整理してください:

1. 接続されているツール・API一覧
2. 各ツールの付与スコープ
3. 現在のタスク定義で実際に使用しているツール
4. 使用していないツール、または過剰なスコープがあるツール
5. 不可逆的な操作が可能なツール

設定ファイル:[設定ファイルの内容を貼り付け]

新規エージェント設計時のアプローチ

「必要なものだけ追加する」原則を徹底する。最初は権限ゼロからスタートし、機能要件を1つ追加するたびに必要な最小スコープだけを付与する。開発の便利さのために「とりあえず全部」と追加した権限が、後のセキュリティレビューで問題になるケースが多い。

チームでの運用

権限変更をコードレビューの対象に含めることが重要だ。エージェントの設定ファイル(ツール一覧・スコープ定義)をバージョン管理し、追加・変更があれば理由をコメントで記録する習慣をつける。


注意点


監査ログの要件

最小権限設計と並行して、ツール呼び出しの監査ログを整備しておくことが重要だ。権限が侵害された場合の事後調査や、エージェントの予期しない動作の原因究明に不可欠になる。

最低限のログに含めるべき要素:

  • What: 呼び出したツール名・操作種別
  • When: タイムスタンプ(UTC)
  • Who: 実行をトリガーしたユーザーID・セッションID
  • Input: ツールへの入力(機密情報はマスキング)
  • Output: ツールの実行結果・エラー内容
  • Result: 成功/失敗
# 監査ログ出力の実装例(概念的なコード)
import json
import time
from datetime import datetime, timezone

def log_tool_call(
    tool_name: str,
    user_id: str,
    session_id: str,
    input_data: dict,
    output_data: dict,
    success: bool
) -> None:
    """ツール呼び出しを監査ログに記録する"""
    
    log_entry = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "tool": tool_name,
        "user_id": user_id,
        "session_id": session_id,
        "input_summary": _mask_sensitive(input_data),
        "success": success,
        "error": output_data.get("error") if not success else None,
    }
    
    # 改ざん防止のため、追記専用のログストレージに書き込む
    append_to_immutable_log(json.dumps(log_entry))

def _mask_sensitive(data: dict) -> dict:
    """機密フィールドをマスキングする"""
    sensitive_keys = {"password", "token", "secret", "api_key", "credential"}
    return {
        k: "***MASKED***" if k.lower() in sensitive_keys else v
        for k, v in data.items()
    }

よくある質問(FAQ)

FAQ

よくある質問

LLMエージェントの最小権限設計について

最小権限設計はどの段階から始めるべきですか?

設計フェーズの最初から取り組むのが理想だ。ツール選定と同時に必要スコープを定義する習慣をつけよう。既存のエージェントには、まず現状の権限棚卸しから始める。後付けで絞り込む場合、動作に影響しない権限の特定に時間がかかることがある。

Human-in-the-Loop を入れると UX が悪化しませんか?

承認ゲートをすべての操作に挟めばそうなる。リスク分類を明確にして、本当に不可逆的・破壊的な操作だけに限定するのがポイントだ。日常的なデータ参照や検索は自動実行のまま残し、「削除」「公開」「課金」などの操作だけを承認対象にすることで、UX とセキュリティを両立できる。

エージェントにシステムプロンプトで権限制御の指示を書けば十分ですか?

十分ではない。プロンプトインジェクション攻撃では、外部から取り込んだデータにシステムプロンプトを上書きする指示が埋め込まれる可能性がある。権限制御はアプリケーション層・インフラ層で実施し、プロンプトはあくまで補助的な役割に留めるのが原則だ。

OWASPのLLM06の公式ドキュメントはどこで確認できますか?

OWASP GenAI の公式サイト(https://genai.owasp.org/)とGitHub(https://github.com/OWASP/www-project-top-10-for-large-language-model-applications)で確認できる。PDFバージョンも公開されており、LLM06:2025の緩和策一覧が詳しく記載されている。

マルチエージェントの場合、権限設計はどう変わりますか?

オーケストレーターエージェントからサブエージェントへの権限移譲が発生するため、複雑さが増す。基本原則は同じ(各エージェントに最小スコープのみ付与)だが、エージェント間の認可伝播の設計が追加で必要になる。この点については、エフェメラル認証情報を使ったマルチエージェント認可伝播の記事で詳しく扱う予定だ。


まとめ

OWASP LLM06:2025「Excessive Agency」は、エージェントの権限設計における3つの問題次元(機能・権限・自律性)を定義したリスクカテゴリだ。攻撃を防ぐことだけでなく、エージェントの誤動作や意図しない動作による被害の上限を設計段階で制御することが目的になる。

本記事で整理した実装チェックリストのポイントは以下の4点だ。

  1. ツール数を絞る:使わないツールを接続しない
  2. スコープを絞る:各ツールに必要最小限の権限のみ付与する
  3. 自律性を制御する:不可逆的・破壊的操作には人間の承認ゲートを挟む
  4. 監査する:すべてのツール呼び出しをログに記録する

「後で絞ろう」は機能しない。開発初期から権限設計を組み込み、追加するたびにスコープを明示的に定義する習慣が、長期的なエージェントセキュリティの基盤になる。


次に読むおすすめ

AIエージェントのセキュリティ設計を体系的に学びたい方は、LLM06を含むOWASP Top 10の全体像や実践的な対策をまとめたnote記事も参考にしてほしい。

noteで続きを読む


参考リンク