結論:AIエージェントのシークレット管理は「置き場所」「取得タイミング」「最小権限」「漏洩検知」の4軸で設計すれば、本番運用のリスクを大幅に下げられます。
- 要点1:APIキーをソースコードや環境変数にベタ書きするのは最も危険なアンチパターン。HashiCorp VaultやクラウドのSecrets Managerで集中管理し、実行時に動的取得するのが現在の標準です。
- 要点2:LLMはプロンプト・出力・ログ経由でシークレットを漏洩させる固有のリスクを持つ。ツール側での注入、出力フィルタリング、ログのredactionを組み合わせてブロックしてください。
- 要点3:鍵が漏洩したときの初動は「即時失効→ローテーション→監査ログ確認→影響範囲特定」の順。平時から手順を確立しておくことが重要です。
対象読者:本番でAIエージェントを運用しているエンジニア・セキュリティ担当・プラットフォームチーム
今日やること:自分のエージェントコードを開き、APIキーがハードコードされていないか・環境変数でベタ書きされていないかを確認する
AIエージェントでシークレット管理が特に難しい3つの理由
従来のWebアプリケーションでもシークレット管理は重要なテーマでしたが、AIエージェントになると難易度が格段に上がります。複数のプロジェクトでエージェントのセキュリティ設計を見てきた経験から、以下の3点が特に厄介だと感じています。
1. 接続先が急増し、鍵の数が爆発する
AIエージェントは性質上、多数の外部ツールやAPIと接続します。Slack・GitHub・Notion・各種SaaS・データベース・外部のLLM API……ひとつのエージェントが10を超えるサービスに接続することは珍しくありません。接続先が増えれば増えるほど、管理すべきシークレットの数も増加し、「どの鍵がどのエージェントに使われているか」の把握が困難になります。静的な鍵を大量に抱えた状態で本番運用を続けることは、それだけで大きなリスクです。
2. LLMがシークレットをプロンプト・出力・ログに漏洩させるリスク
これはAIエージェント固有の問題です。OWASP LLM Top 10では「LLM02: Sensitive Information Disclosure(機密情報の開示)」および「LLM07: System Prompt Leakage(システムプロンプト漏洩)」として分類されています。具体的には次のような経路で漏洩が起きます。
- システムプロンプトにAPIキーを直接埋め込んでいると、プロンプトインジェクション攻撃で抽出される
- LLMがデバッグ目的でシークレットを出力に含めることがある
- 会話履歴をログに保存する際、コンテキスト内に入り込んだ鍵がそのままログファイルに記録される
3. 自律実行で人間の目が届きにくい
エージェントは24時間自律的に動作します。人間がリアルタイムで全ての操作を監視するのは現実的ではなく、鍵が漏洩してもしばらく気づかないというリスクが常に存在します。漏洩後の被害を最小化するには、漏洩検知の仕組みを平時から作り込むことが必須です。

シークレットを置いてはいけない場所:アンチパターン早見表
まず「やってはいけないこと」を整理します。以下の表は、よく見かけるアンチパターンとそのリスクをまとめたものです。
| 保管場所・手法 | 判定 | 主なリスク | 代替策 |
|---|---|---|---|
| ソースコードにハードコード | ❌ 絶対NG | Git履歴に残り、リポジトリ公開で即漏洩 | Secrets Managerで実行時取得 |
| .envファイルをGitにコミット | ❌ 絶対NG | .gitignore設定ミスで公開リポジトリに流出 | .gitignoreに追加、Vaultで管理 |
| 環境変数にベタ書き(CI/CD含む) | ⚠️ 要注意 | ログ出力・デバッグで露出、長期間ローテされない | 短命トークン+定期ローテーション |
| システムプロンプト本文に記載 | ❌ 絶対NG | プロンプトインジェクションで抽出、出力に混入 | ツール関数の内部でのみ注入 |
| 会話履歴(コンテキスト)に含める | ❌ 絶対NG | ログ・デバッグUI・会話エクスポートで漏洩 | ツール呼び出し時のみ渡す |
| アプリケーションログにそのまま出力 | ❌ 絶対NG | ログ集約基盤・監視ツールに平文で流れる | redaction(マスキング)を実装 |
| 集中管理Vault+実行時動的取得 | ✅ 推奨 | — | (これが正解) |
| 短命トークン(TTL付き) | ✅ 推奨 | — | (これが正解) |
特に「環境変数だから大丈夫」という誤解が多いです。環境変数はプロセスから子プロセスに継承されるため、想定外の場所からアクセスされるリスクがあります。また、一度設定したら何年もローテーションされないケースが多く、long-lived credentialとして大きなリスクになります。
シークレットストア(Vault)の実践的な使い方
シークレット管理の現在の標準は、HashiCorp VaultやクラウドのSecrets Managerを使った集中管理です。AIエージェントに特に有効なのは、動的シークレット(Dynamic Secrets)の仕組みです。リクエストのたびにVaultが新しい認証情報を生成し、TTL経過後に自動失効させます。漏洩しても時間で無効化されるため、被害範囲を時間軸で区切れる点が大きなメリットです。
主要シークレットストアの特徴
2026年6月時点での主要プラットフォームの特徴を整理します。
- HashiCorp Vault(公式チュートリアル: Dynamic Secrets):オープンソース+エンタープライズ版。動的シークレット・短命トークン・ポリシーベースのアクセス制御が強力。AIエージェントのID連携(OIDC/JWT認証)も対応済み。
- AWS Secrets Manager:AWS環境での利用に最適化。RDS・Redshift等のLambdaによる自動ローテーションが組み込まれている。エージェントへの配布はIAMロール+AssumeRoleで最小権限制御。
- Google Cloud Secret Manager:グローバルリソースとしてバージョン管理。Cloud IAMとの統合が深い。ローテーションはPub/Sub通知+Cloud Functionで実装する(自動生成はしないため実装コストがある)。
- Azure Key Vault:シークレット・鍵・証明書を一元管理。FIPS 140-2準拠のHSMバックアップが使える。任意シークレットの自動ローテーションはAzure Functions連携が必要。
実行時に動的取得する実装パターン
エージェントのツール呼び出し直前にVaultからシークレットを取得する基本パターンです。「LLMがシークレットを直接知らない設計」にすることがポイントです。
動作環境:Python 3.11+、hvacライブラリ(HashiCorp Vault公式クライアント)、サービスアカウントトークン認証を想定
import hvac
import os
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
# VAULT_ADDR と VAULT_TOKEN は環境変数から取得(コードにハードコードしない)
def get_secret(secret_path: str, key: str) -> str:
"""
HashiCorp VaultからシークレットをKV v2形式で取得する。
エージェントのツール関数の内部から呼び出すことで、
LLMのコンテキスト(プロンプト/出力)にシークレットが混入しない設計にする。
"""
client = hvac.Client(
url=os.environ["VAULT_ADDR"],
token=os.environ["VAULT_TOKEN"], # 短命トークン(TTL: 15〜30分推奨)
)
if not client.is_authenticated():
raise RuntimeError(
"Vault認証に失敗しました。VaultアドレスとトークンTTLを確認してください。"
)
# KV v2 エンジンからシークレットを取得
response = client.secrets.kv.v2.read_secret_version(
path=secret_path,
mount_point="secret",
)
return response["data"]["data"][key]
def call_external_api_tool(endpoint: str, payload: dict) -> dict:
"""
エージェントのツール関数の例。
APIキーはLLMに渡さず、この関数の内部で取得・使用する。
LLMには「ツールを呼び出した結果」だけを返す。
"""
# シークレットはツール関数内部でのみ取得。LLMのコンテキストに漏れない。
api_key = get_secret("agents/my-agent/external-api", "api_key")
import requests
headers = {"Authorization": f"Bearer {api_key}"}
response = requests.post(endpoint, json=payload, headers=headers)
response.raise_for_status()
# api_key をレスポンスに含めない。LLMのコンテキストに漏れないようにする。
return {"status": response.status_code, "data": response.json()}
ポイントは3つです。①VAULT_ADDRとVAULT_TOKENはコードにハードコードせず環境変数から取得する。②get_secret()はツール関数の内部からのみ呼び出す(LLMのプロンプトや会話履歴には渡さない)。③返却値にシークレットを含めず、LLMのコンテキストへの混入を防ぐ。このパターンにすることで、プロンプトインジェクション攻撃でシークレットを引き出される攻撃面(attack surface)を大幅に削減できます。
ローテーション運用:定期交換と漏洩時の即時失効
シークレットは一度設定したら終わりではありません。定期的なローテーションと、漏洩時の即時失効の手順を平時から整備しておくことが重要です。
TTLの目安
- エージェントの1タスク実行単位:TTL 15〜30分。タスク完了後に自動失効。
- 長時間バッチ処理:TTL 4〜8時間。処理完了後にlease revoke。
- 静的シークレットが避けられない場合:30〜90日ごとにローテーション。AWS Secrets ManagerのLambda自動ローテーション等を活用。
ゼロダウンタイムでの切り替え手順
APIキーをローテーションする際、古いキーを即削除すると既存のエージェントプロセスが認証エラーを起こします。ゼロダウンタイムで切り替えるには次のフローが実用的です。
- 新しいキーを発行:外部サービスの管理画面またはVaultのdynamic secretsで新キーを生成。
- 新旧両方のキーを一時的に有効にする:Vaultに新バージョンを追加しつつ、旧バージョンを残す(dual-active期間。24〜72時間が目安)。
- エージェントを新キーで再起動:Kubernetes Podのrolling update、またはエージェントプロセスの順次再起動。
- 旧キーを失効させる:全エージェントが新キーで動作していることを確認後、旧バージョンを削除・revoke。
- 監査ログで確認:Vault audit logやCloudTrailで旧キーへのアクセスがゼロになったことを確認してから完了とする。
漏洩検知:secret scanningの導入
GitGuardian・truffleHog・GitHub Secret Scanningなどをリポジトリに設定することで、APIキーなどのパターンをCIパイプラインの段階で検知できます。コミット前のpre-commitフックに組み込むことで、人的ミスをコードレビュー前に機械的にブロックする層を設けられます。
最小権限設計:エージェントごとに鍵を分離する
「とりあえず全権限のAPIキーを1本作って全エージェントで使い回す」という運用は最もリスクが高いパターンです。1本の鍵が漏洩しただけで、全システムへの操作が危険にさらされます。被害範囲(Blast Radius)を最小化するための権限分離が不可欠です。
権限分離の基本方針
- エージェント単位でキーを発行:「注文処理エージェント」「顧客対応エージェント」など、役割ごとに別々のAPIキーを使う。
- スコープを最小化する:読み取りのみでよいエージェントにwrite権限を与えない。GitHubのfine-grained tokenでリポジトリとオペレーションを絞る例が典型的です。
- read-onlyとwrite権限を分離:データ取得エージェントはread-only鍵、データ更新エージェントだけにwrite鍵を付与する。
- ツールごとにスコープを絞る:エージェント内の個々のツール呼び出しに必要な権限だけを持つ短命トークンをVaultから取得する設計が理想。
VaultのPolicy設定例
HashiCorp Vaultのポリシーでエージェントのアクセス範囲を絞る例です。このポリシーを各エージェントのサービスアカウントに割り当てることで、あるエージェントが侵害されても他のエージェントや管理用シークレットへのアクセスを防げます。
# 注文処理エージェント専用ポリシー
# このエージェントは "agents/order-agent/" 配下のシークレットのみ読み取り可能
path "secret/data/agents/order-agent/*" {
capabilities = ["read"]
}
# 他エージェントや管理用シークレットへのアクセスは明示的に拒否
path "secret/data/agents/admin/*" {
capabilities = ["deny"]
}
path "secret/data/agents/crm-agent/*" {
capabilities = ["deny"]
}
LLM固有の漏洩防止:出力フィルタとログのredaction
AIエージェント特有の対策として、LLMの出力経路とログ経路での漏洩防止が不可欠です。
プロンプトにシークレットを入れない設計
前述のとおり、シークレットはツール関数の内部でのみ扱い、LLMのプロンプト本文・システムプロンプト・会話履歴に一切含めないことが原則です。このアーキテクチャ上の分離が最も効果的な漏洩防止策であり、他のどの対策よりも優先して実装すべき内容です。
ログのredaction(マスキング)実装
万が一シークレットがログに混入した場合に備え、ログ出力時点でマスキングする仕組みを実装します。個々のlogger.info()呼び出しを修正するアプローチは漏れが発生しやすいため、フィルターレイヤーで一括マスキングする方が堅牢です。
動作環境:Python 3.11+、標準ライブラリのloggingモジュールを使用
import logging
import re
class SecretRedactionFilter(logging.Filter):
"""
ログ出力に含まれるAPIキー・トークン形式の文字列を自動マスキングする。
本番環境ではロガーにこのフィルターを必ずアタッチする。
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
# マスキング対象のパターン(APIキー・JWTトークン・OAuthトークン等)
SECRET_PATTERNS = [
(re.compile(r'sk-[a-zA-Z0-9]{20,}'), "sk-***REDACTED***"),
(
re.compile(
r'eyJ[a-zA-Z0-9_\-]{20,}\.eyJ[a-zA-Z0-9_\-]+\.[a-zA-Z0-9_\-]+'
),
"***JWT_REDACTED***",
),
(re.compile(r'Bearer\s+[a-zA-Z0-9_\-\.]{20,}'), "Bearer ***REDACTED***"),
(
re.compile(r'api[_-]?key["\s:=]+["\']?([a-zA-Z0-9_\-]{16,})'),
"api_key=***REDACTED***",
),
]
def filter(self, record: logging.LogRecord) -> bool:
message = record.getMessage()
for pattern, replacement in self.SECRET_PATTERNS:
message = pattern.sub(replacement, message)
record.msg = message
record.args = ()
return True
# ロガーの設定
logger = logging.getLogger("agent")
logger.addFilter(SecretRedactionFilter())
# 使用例(マスキングされて出力される)
logger.info("APIキーを取得しました: sk-proj-abcdefghijklmnopqrstuvwxyz")
# 出力: APIキーを取得しました: sk-***REDACTED***
このフィルターはロガーインスタンスにアタッチするだけで全ログ出力に適用されます。パターンリストは実際に使っているトークン形式に合わせて拡張してください。Datadogなどのログ集約基盤に転送する前にredactionが適用されていることを、テスト環境で必ず確認することを推奨します。
【要注意】よくある失敗パターンと回避策
失敗1:全エージェントで同一の「管理者権限キー」を使い回す
「とりあえず動けばいい」で始めた開発が本番に流れるケースです。1本のキーが漏洩した瞬間に全システムが危険にさらされます。
回避策:エージェント単位・ツール単位でスコープを絞ったキーを発行し、Vaultのポリシーで管理する。初期の手間は大きいですが、後から分離しようとする方がはるかにコストがかかります。
失敗2:ローテーション手順を「その時になって考える」
「いざ漏洩した」という緊急時に初めてローテーション手順を考えるケースが実際に多いです。慌てた状態で手順を考えると、ダウンタイムが発生したり、影響範囲の特定が遅れたりします。
回避策:本番稼働前に「漏洩インシデント対応ランブック」を書き、定期的なローテーション演習を実施する。手順書は実際に1回試してみることで初めて実用的になります。
失敗3:エージェントのログを「無害」だと思い込む
エージェントはデバッグ・トレース目的で詳細なログを出すことがあります。LLMに渡したコンテキスト全体がログに出力されていることに気づかず、Datadogなどの監視基盤に平文でシークレットが流れ込むケースがあります。
回避策:ログのredactionフィルターを実装し、監視基盤への転送前にマスキングされていることをテスト環境で確認する。
漏洩検知と事故対応:鍵が漏れたときの初動
どれだけ対策を施しても、漏洩リスクをゼロにすることはできません。重要なのは「漏洩を前提にした設計」と「素早い初動対応」です。
初動の4ステップ
- 即時失効(Revoke):漏洩が疑われるキーを最優先で無効化します。HashiCorp Vaultなら
vault lease revoke、AWS Secrets Managerならキーの無効化、外部サービスなら管理コンソールから削除します。「まず調査してから失効」ではなく「まず失効してから調査」が原則です。 - 新しいキーの発行とローテーション:失効と同時並行で新しいキーを発行し、影響を受けたエージェントを新キーで再起動します。
- 監査ログの確認:VaultのAudit Log、CloudTrail、外部サービスのアクセスログを確認し、「漏洩したキーがいつから・どこで・どのように使われたか」を特定します。
- 影響範囲の特定と通知:不正アクセスで取得されたデータの種類・量・期間を特定し、必要に応じて社内のセキュリティチームおよび関係するサービスプロバイダーに通知します。個人情報が含まれる可能性がある場合は、組織のセキュリティポリシーに従い、専門家への相談も検討してください。
平時の準備:漏洩を前提にした設計の要点
- 短命トークンの活用:TTL付きの動的シークレットは、漏洩しても有効期限が切れれば無効化される。被害を時間で区切れる最も効果的な対策です。
- アクセスログの定期レビュー:異常なAPIアクセスパターン(深夜の大量アクセス、未知のIPからのアクセス)を検知するアラートを設定する。
- 最小権限による被害最小化:漏洩したキーのスコープが狭ければ、攻撃者がアクセスできるリソースも限定される。
まとめ:AIエージェントのシークレット管理4原則
本記事で解説した内容を4原則に集約します。
- 置き場所を集中管理する:ソースコード・環境変数・プロンプトにシークレットを置かない。HashiCorp VaultやクラウドのSecrets Managerで集中管理し、実行時に動的取得する。
- LLMのコンテキストから完全に分離する:シークレットはツール関数の内部でのみ扱い、LLMのプロンプト・出力・ログに混入しない設計にする。出力フィルタとログのredactionで多層防御する。
- 最小権限で権限を分散する:エージェント・ツール単位でスコープを絞ったキーを発行し、1本の漏洩による被害範囲(Blast Radius)を最小化する。
- 漏洩を前提に速やかに失効できる設計にする:短命トークン・監査ログ・ローテーション手順を平時から整備し、「漏洩したらすぐ失効」の初動ができる状態を維持する。
正直にお伝えすると、これらの対策を全て一度に実装するのは大変です。まずは「ソースコードのsecret scanning導入」と「Secrets Managerへの移行」の2点から始めるのが現実的なアプローチです。小さな一歩から、確実にセキュリティレベルを上げていきましょう。運用全体の設計はAIエージェント障害対応・オンコール運用ガイドも参照してください。
よくある質問
- Q. AIエージェントのシークレット管理で最初に着手すべきことは何ですか?
- A. まずソースコードとGit履歴にシークレットがハードコードされていないかを確認することを推奨します。truffleHogやGitGuardianなどのsecret scanningツールを使えば自動検出できます。次に、環境変数でのベタ書きをSecrets Manager(AWS/GCP/Azure)またはHashiCorp Vaultに移行する手順を計画してください。
- Q. HashiCorp VaultとAWS Secrets Managerはどちらを選ぶべきですか?
- A. インフラがAWSで完結しているチームにはAWS Secrets Managerが導入コストが低く推奨されます。マルチクラウド構成や、動的シークレット・柔軟なポリシー管理が必要な場合はHashiCorp Vaultが適しています。どちらも2026年6月時点で本番運用の実績があります。
- Q. 短命トークン(TTL付きシークレット)のTTLはどのくらいが適切ですか?
- A. エージェントの1タスク単位なら15〜30分、長時間バッチ処理なら4〜8時間が目安です。静的シークレットが避けられない場合は30〜90日ごとのローテーションを実施してください。TTLが短いほどセキュリティは高まりますが、トークン取得の頻度とVaultへの負荷のトレードオフを考慮して設定してください。
- Q. APIキーが漏洩した疑いがある場合、最初に何をすべきですか?
- A. 「まず調査してから失効」ではなく「まず失効してから調査」が原則です。漏洩が疑われるキーを即時無効化し、新しいキーに切り替えてください。その後、監査ログで不正アクセスの有無・範囲を確認します。個人情報が含まれる可能性がある場合は、組織のセキュリティポリシーに従い専門家への相談も検討してください。
- Q. OWASPのLLM Top 10でシークレット管理に関連するリスクはどれですか?
- A. 主に3つのリスクが関連します。LLM01(プロンプトインジェクション)は攻撃者がシステムプロンプトに含まれるシークレットを抽出する手法です。LLM02(機密情報の開示)はAPIキーなどの認証情報がLLMの出力に含まれるリスクです。LLM07(システムプロンプト漏洩)はシステムプロンプトに記載したシークレットがユーザーに見えてしまうリスクです。詳細はOWASP公式ページを参照してください。
この記事を読んでAIエージェントのセキュリティ設計に課題を感じた方へ
UravationではAIエージェント導入の研修・コンサルを行っています。シークレット管理を含むセキュリティ設計から運用まで、実務ベースでご支援します。
AIエージェント運用シリーズ
