最適化、テスト、セキュリティ

プロンプト内の個人情報とシークレットの検出

API キー、パスワード、個人データが LLM プロンプトに入り込む経緯、機密情報検出の仕組み、何かを送信する前にマスクする方法。

英語の原文からの翻訳です。コード、プロンプト、モデルの出力は英語のまま掲載しています。

ホスト型モデルに送られるプロンプトは、すべてあなたの環境の外に出ます。そこに API キー、パスワード、顧客の個人データが含まれていれば、その情報は他者のシステムにあり、場合によっては双方のログにも残ります。機密情報の検出とは、プロンプトを送信する前にそのような内容を見つけることです。

機密データがプロンプトに入る経路

意図的であることはまれです。よくある経路は次のとおりです。

  • 貼り付けられたログやスタックトレース。 トークン、接続文字列、セッション Cookie が含まれていることがあります。
  • デバッグのために共有された設定ファイル。 .env、YAML、Terraform など。
  • ハードコードされた認証情報を含むコード。
  • サポートチケット、メール、チャットの記録にある顧客データ。
  • 質問に必要な量を超えて含む、取得されたドキュメント。
  • リポジトリ内のプロンプトファイル。 誰かが本物のキーでテストした場合。
  • エージェントのループ内のツール結果。 フィルターされずにモデルへ転送される場合。

2 つのカテゴリ、2 種類のリスク

シークレットはアクセスを与えます。API キー、トークン、パスワード、秘密鍵、接続文字列などです。漏れたシークレットは、すぐに悪用されえます。対応は、失効させてローテーションすることです。

**個人データ(PII)**は人を特定します。氏名、メールアドレス、電話番号、住所、決済カード番号、国民 ID 番号などです。送信すると、プライバシーの約束や法律に違反する可能性があり、ローテーションもできません。

検出の仕組み

検出器は、いくつもの方法を組み合わせます。それぞれに死角があるからです。

既知の形式。 多くのプロバイダーは、識別しやすいプレフィックスと長さを持つキーを発行します。これらは高い確度で一致させられます。

文脈パターン。 password = "..." や api_key: ... のような代入は、形式にかかわらず、その値を認証情報として示します。

エントロピー。 ランダムな文字列はシャノンエントロピーが高くなります。「token」や「secret」のような語の隣にある、長くエントロピーの高い値は、未知の形式であっても認証情報である可能性が高いです。

構造化された識別子。 メールアドレス、電話番号、カード番号にはパターンがあります。カード番号は、チェックサムで確認できます。

固有表現認識。 統計モデルが、固定パターンのない氏名、組織名、地名を見つけます。カバー範囲は広がりますが、誤検出も増え、モデルが必要です。

PromptFlowEngine のプロンプトセキュリティスキャナーは、最初の 4 つを使います。決定的でローカルで実行されるため、シークレットを調べるテキストが、チェックのためにどこかへ送られることはありません。

値ではなく位置を報告する

見つけたシークレットを出力する検出器は、ログやターミナルにシークレットの 2 つ目のコピーを作ってしまいます。行儀の良いスキャナーは、カテゴリと位置だけを返します。

{
  "hasSensitiveData": true,
  "countsByCategory": { "api_key": 1, "email": 1 },
  "matches": [
    { "category": "api_key", "start": 118, "end": 164 },
    { "category": "email", "start": 176, "end": 196 }
  ]
}

これが、PromptFlowEngine がすべてのインターフェースで返す形式です。具体例は機密データのルールを参照してください。

マスク

マスクは、検出された各値を、周囲のテキストの意味を保つプレースホルダーに置き換えます。

Before: Connect with postgres://admin:hunter2@db.internal:5432/app
After:  Connect with [REDACTED_CONNECTION_STRING]

[REDACTED_API_KEY] のような型付きのプレースホルダーは、アスタリスクの列より優れています。モデルがそこにどんな種類のものがあったかを知ったまま、中身を見ずに「接続文字列の形式がおかしいようだ」のように推論できるからです。

タスクが参照する必要のある個人データには、1 つのリクエスト内で一貫した仮名を使います。同じメールアドレスの出現はすべて [EMAIL_1] になり、次のアドレスは [EMAIL_2] になります。モデルは人を区別でき、アプリケーションは応答の後でプレースホルダーを元に戻せます。

チェックを置く場所

できるだけ早く、複数の場所で検出します。

場所 捕まえるもの
エディターまたはチャット欄 貼り付け。送信前に
API 呼び出し前のアプリケーションコード ユーザー、レコード、検索由来のデータ
エージェントのステップ間 コンテキストに入ろうとしているツール結果
CI、プロンプトファイル上 リポジトリにコミットされた認証情報
ログ記録の前 保存されようとしている内容

Chrome 拡張機能は、ChatGPT、Claude、Gemini での下書きにシークレットが含まれていると警告し、お使いのデバイス上でマスクできます。VS Code 拡張機能は、プロンプトをチャットに送る前にプライバシーガードを実行し、strict、redact、warn のモードがあります。CI では、チェックゲートが既定で重大な検出があれば失敗するため、コミットされたキーはビルドを止めます。

ポリシーの選択:ブロック、マスク、警告

  • ブロック:シークレットを絶対に送ってはならない場合。最も安全で、最も支障が大きい。
  • マスク:既定として。機密の値を除いてプロンプトが通る。
  • 警告:コード内の誤検出の可能性など、人が判断すべき場合。

どれを選ぶにしても、シークレットの検出はローカルで行ってください。送っても安全かどうかを調べるために、テキストをリモートのサービスへ送るチェックは、目的を損ないます。

知っておくべき限界

  • 見逃し。 珍しい形式のシークレットや、人物の描写のようにパターンのない個人データは、すり抜けることがあります。検出はリスクを減らしますが、プロンプトが安全だと保証するものではありません。
  • 誤検出。 ハッシュ、UUID、テスト用のフィクスチャは、シークレットに見えることがあります。チェックを無効にするのではなく、既知の安全な値を許可リストに入れてください。
  • 画像とファイル。 テキストスキャナーは、事前に変換しない限り、スクリーンショットや PDF を読みません。
  • 文脈。 名前は、ある場面では公開情報で、別の場面では機密です。それを決められるのは、あなたのポリシーだけです。

検出を超えて:送る量を減らす

最も確実な対策は、そもそもデータを含めないことです。

  • ID を渡し、ツールにレコードを検索させる。そうすれば、モデルは不要なフィールドを目にしません。
  • プロンプトを組み立てる前に、フィールドを取り除く。
  • 認証情報はアプリケーション内に置き、ツールに直接渡す。ツールに API を呼ばせるために、モデルがあなたの API キーを必要とすることはありません。
  • 例やプロンプトファイルにはテストデータを使う。

すでにシークレットを送ってしまった場合

  1. ただちに失効させ、ローテーションする。侵害されたものとして扱う。
  2. アクセスログで使用の形跡を確認する。
  3. リポジトリの履歴とプロンプトファイルから取り除く。
  4. 次回は同じ経路を捕まえられるよう、チェックを追加する。

周辺の脅威モデルについては、プロンプトセキュリティを参照してください。データがコンテキストに入った後にそれを抜き出そうとする攻撃については、プロンプトインジェクションを参照してください。

実践してみる

プロンプトセキュリティで試す

インジェクション表現、漏えいした秘密情報、個人データを検出し、伏せ字にします。 無料・決定論的で、アカウントは不要です。

関連する PromptFlowEngine ツール

最適化、テスト、セキュリティのその他のガイド

プロンプトエンジニアリングガイドをすべて見る