エラーログをAIに貼る前の伏せ字ルール:トークン・パス・メールの置き換え方
AIを使いこなすClaudeで執筆し、GPTで自動校閲・修正しています。

結論から言うと、ログは「黒塗り」ではなく「名前付きの代役への置き換え」で伏せるのが安全で、しかも調査にも使えます。トークンやパスワードは値を丸ごと <TOKEN_1> のようなラベルに替えます。ホームディレクトリのユーザー名やメールアドレス、社内ホスト名も同様に替えます。一方で、エラーの種類、メッセージ、行番号、関数名、ライブラリのバージョン、プロジェクト内の相対パス、HTTPステータスはそのまま残します。AIが原因を推測する材料は、ほとんどこの「残す側」にあるからです。 この記事では、置き換えの原則、置き換え前後の対応例、残す・消す・迷うの判断表、貼る直前に全行を見直すチェックリスト、AIに渡す依頼文を順に示します。
置き換えの原則:ラベルは一貫させ、形は残す
伏せ字で失敗しやすいのは、*** や xxxx で全部を同じ見た目にしてしまうことです。次の3点を守ると、情報の欠落を最小限にできます。
- 同じ値には同じラベルを付ける。 同じメールアドレスが3行に出るなら、3行とも <EMAIL_1> にします。別の人なら <EMAIL_2> です。「同じユーザーで失敗している」のか「別々のユーザーで失敗している」のかが読み取れます。
- 種類が分かるラベルにする。 <TOKEN_1>、<DB_PASS>、<HOST_DB> のように、何の値かを名前で示します。
- 形が原因になりうるときは、形を文章で補う。 「トークンの形式が不正」というエラーなら、長さや先頭の特徴が手がかりになります。その場合も実際の値は書かず、<TOKEN_1>(英数字40文字、先頭に Bearer が付く) のように説明だけを添えます。
ログに出してはいけない情報の考え方は、OWASP Logging Cheat Sheet が参考になります。この資料は、パスワード、暗号鍵、セッションID、アクセストークン、データベース接続文字列などを、ログから除外するか、マスク・ハッシュ化などをすべき対象に挙げています。ファイルパスや内部ネットワーク名、氏名・メール・電話番号のような情報も、リスク評価や規制に応じて特別な扱いが要りうると述べています。AIに貼る場合も、ログを外部に持ち出す行為である点は同じなので、この線引きをそのまま使えます。
置き換え前後の対応例
次は説明用の例です。値はすべて架空で、実際のサービスのログではありません。
置き換え前:
Error: connect ECONNREFUSED 10.0.12.34:5432
at /Users/taro.yamada/work/shop-api/src/db.js:42:11
DATABASE_URL=postgres://shop_admin:Zx9-example-pass@db-internal.example-corp.co.jp:5432/shop
POST /api/login 401 {"email":"hanako.sato@example.co.jp"}
Authorization: Bearer EXAMPLE-TOKEN-0000000000000000置き換え後:
Error: connect ECONNREFUSED <IP_DB>:5432
at /Users/<USER>/work/shop-api/src/db.js:42:11
DATABASE_URL=postgres://<DB_USER>:<DB_PASS>@<HOST_DB>:5432/<DB_NAME>
POST /api/login 401 {"email":"<EMAIL_1>"}
Authorization: Bearer <TOKEN_1>変えた箇所と、残した箇所の理由を整理します。
- 10.0.12.34、置き換え:<IP_DB>、理由:社内ネットワークの構成が分かるため。ポート 5432 は残す(「接続拒否」の調査でPostgreSQLの標準ポートだと分かる)
- /Users/taro.yamada/、置き換え:/Users/<USER>/、理由:氏名由来のユーザー名が入りやすいため。work/shop-api/src/db.js:42:11 は残す(どのファイルの何行目かが原因特定の中心)
- 接続文字列のユーザー・パスワード・ホスト・DB名、置き換え:<DB_USER> <DB_PASS> <HOST_DB> <DB_NAME>、理由:接続文字列は丸ごと秘密として扱う。postgres:// と全体の構造は残す
- メールアドレス、置き換え:<EMAIL_1>、理由:後述の理由で個人情報にあたりうるため
- Bearerトークン、置き換え:<TOKEN_1>、理由:そのまま使われると認証を突破される値のため。Bearer という方式名は残す
Error: connect ECONNREFUSED の行、401、POST /api/login といった部分は一切変えていません。このままでもAIは「DBに接続できていない」「ログインAPIが401を返している」と読み取れます。
残す・消す・迷うの判断表
- エラー名・メッセージ本文、扱い:残す、置き換え例・メモ:メッセージに値が埋め込まれている場合だけ、その値を置き換える
- 行番号・列番号・関数名、扱い:残す、置き換え例・メモ:原因調査の主な手がかり
- ライブラリ・ランタイムのバージョン、扱い:残す、置き換え例・メモ:既知の不具合との照合に使える
- プロジェクト内の相対パス、扱い:残す、置き換え例・メモ:src/db.js:42 のような形
- HTTPメソッド・パス・ステータス、扱い:残す、置き換え例・メモ:クエリ文字列(?token=... など)は別扱い
- APIキー・トークン・パスワード・Cookie・セッションID、扱い:必ず置き換える、置き換え例・メモ:<TOKEN_1>、<SESSION_1> など
- 接続文字列・秘密鍵・署名付きURL、扱い:必ず置き換える、置き換え例・メモ:全体を <DB_URL> にしてもよい
- 絶対パス中のユーザー名、扱い:置き換える、置き換え例・メモ:/Users/<USER>/、C:\Users\<USER>\
- メールアドレス・氏名・電話番号、扱い:置き換える、置き換え例・メモ:<EMAIL_1>、<NAME_1>
- 社内ホスト名・内部IP・社内URL、扱い:置き換える、置き換え例・メモ:<HOST_DB>、<IP_DB>
- 顧客ID・注文番号、扱い:迷う、置き換え例・メモ:他の情報と突き合わせて個人が分かるなら置き換える
- リクエスト/レスポンス本文、扱い:迷う、置き換え例・メモ:構造(キー名)だけ残し、値を置き換える
- タイムスタンプ、扱い:迷う、置き換え例・メモ:順序の調査に必要なら残す。時刻が不要なら削ってよい
メールアドレスを置き換える根拠
個人情報保護委員会のQ&Aは、メールアドレスのユーザー名やドメイン名から特定の個人を識別できる場合(例として kojin_ichiro@example.com のような形)は、そのアドレス単体で個人情報に該当するとしています。それ以外でも、他の情報と容易に照合でき個人を識別できるなら、個人情報にあたる可能性があります(個人情報保護委員会「ガイドライン」に関するQ&A のQ1-4など)。ログのメールアドレスは、同じログ内のユーザーIDや氏名と並んでいることが多いので、迷うより置き換えるほうが確実です。ただしこれは日本の個人情報保護法の考え方の一例で、貼ってよいかどうかの適法性は、所属組織の規程や委託・提供の取り決めで変わります。業務のログなら、社内の情報管理ルールの確認が先です。
手順:貼る前の置き換え作業
- 元のログを複製する。 元のファイルは触らず、コピーに対して作業します。
- 貼りたい範囲を絞る。 エラーが出た箇所の前後と、スタックトレースだけで足りることが多いです。ログ全体を貼る必要はありません。
- エディタの検索機能で、秘密の入口を探す。 token、secret、password、passwd、key、Authorization、Cookie、://(接続文字列やURL)、@(メールや接続文字列)を検索して、該当行を置き換えます。この検索語は取りこぼしを前提とした出発点です。
- ユーザー名を一括置換する。 自分のホームディレクトリ名を全文検索し、<USER> に一括で置換します。一括置換なら、同じ値に同じラベルを自然に付けられます。
- 残りを目で全行読む。 検索で拾えない値(独自形式のID、本文中の氏名など)は、人が読むしかありません。次のチェックリストを使います。
- 置き換えた事実をAIに伝える。 下の依頼文のとおり、ラベルの意味を一行で説明しておきます。
貼り付け前の全行チェックリスト
貼る直前に、上から1行ずつ読んで確認してください。
- [ ] 認証ヘッダー(Authorization、X-API-Key など)の値がラベルになっている
- [ ] Cookie と Set-Cookie の値、セッションIDが残っていない
- [ ] URLのクエリ文字列(?token=、?key=、?signature= など)の値が置き換わっている
- [ ] :// を含む接続文字列で、ユーザー・パスワード・ホスト名が置き換わっている
- [ ] 環境変数の出力(env やデバッグ表示)に秘密の値が混ざっていない
- [ ] JWTのようなトークンは、全体をラベルにしている(JWTは中身を読み取れる形式で、暗号化されているとは限らないため)
- [ ] 絶対パスのユーザー名・会社名・案件名が置き換わっている
- [ ] メールアドレス、氏名、電話番号、住所がラベルになっている
- [ ] 内部IP、社内ホスト名、社内URLが置き換わっている
- [ ] JSON本文やSQLの値の中に、顧客情報が残っていない
- [ ] 同じ値には同じラベル、別の値には別のラベルが付いている
- [ ] エラー名、行番号、バージョン、HTTPステータスは消していない
- [ ] 置き換えのためにファイル全体を貼り直していない(元のログの複製から作業した)
AIに渡す依頼文の例
置き換えが済んだログは、次のように依頼すると、AIが山かっこの中身を聞き返すのを防げます。
次のエラーログの原因と修正方法を教えてください。
【環境】Node.js(バージョン:○○)、Express、PostgreSQL
【やりたいこと】ログインAPIからDBに接続したい
【ログについて】秘密と個人情報は<>のラベルに置き換え済みです。
同じラベルは同じ値を指します。実際の値は送れないので、
値が必要な場合は「どんな形式の値か」を質問してください。
【お願い】
1. 考えられる原因を可能性の高い順に3つまで
2. それぞれを確かめる手順
3. 修正するときは、接続情報を環境変数から読む形で書いてください
--- ログ ---
(ここに置き換え済みログを貼る)「実際の値は送れない」と先に伝えるのがポイントです。AIが「パスワードを教えてください」と返すのを防げますし、コード例にも秘密を直書きしない形で書かせやすくなります。
すでに貼ってしまったときの対応
秘密の値をAIの入力欄、チャット、チケットなどに貼ってしまったら、まずその値を無効にして新しいものに替えることを優先します。GitHubのシークレットスキャンの説明も、秘密が漏れた場合は、履歴から消す作業より先にその認証情報をすぐローテーション(再発行して旧版を失効)するよう勧めています(GitHub Docs: Secret scanning)。これはGitHub上の漏えいを前提にした説明ですが、「見られた可能性のある値は使い続けない」という考え方は、AIへの貼り付けにも当てはまります。
なお、AIサービスの設定で「入力を学習に使わない」にしても、その入力が秘密として守られると保証されるわけではありません。保存期間や社内閲覧の範囲は別の話なので、秘密の値は設定に頼らず、最初から送らないのが基本です。会社のアカウントで使っている場合は、貼ってよい情報の範囲を所属組織のルールで確認してください。
迷ったときの基準
最後に、判断に迷う行への基準を一つだけ挙げます。「その行を消しても、AIが原因を考えられるか」を自問し、考えられるなら置き換えます。 値そのものが原因の手がかりになる場合(形式不正、桁数、文字種など)も、値は書かず、形の説明に替えます。迷う行を残すより、一度置き換えてAIに質問させるほうが、後で取り返しがつかなくなる事態を避けられます。

