秘密の鍵の扱い
AIの道具は、読んだものを文脈としてモデルへ送り、書いたものをコミットし、走らせた命令の出力を記録に残す。鍵はこの流れのどれにも乗せない。漏れたら、消すより先に無効にする。
要点
- 漏れる経路は、コミット、ログと出力、AIへ渡す文脈、設定ファイルの4つ。
- 鍵はリポジトリの外に置き、AIの道具がその場所を読めないよう、拒否の設定とサンドボックスで止める。
- 鍵の権限は用途ごとに最小にし、長く使う鍵より期限の短い資格情報を使う。
- 漏れたら、無効化、差し替え、使われた跡の調査、履歴とログの掃除の順。履歴を書き換えても無効化の代わりにならない。
- GitHub の secret scanning と push protection は最後の網で、置き場所の設計の代わりにならない。
漏れる経路
| 経路 | 起きる形 | 止める所 |
|---|---|---|
| AIへ渡す文脈 | 不具合を調べるため .env や資格情報のファイルを読む。鍵の載ったログを貼る。読んだ中身は会話の一部になる | 読み取りの拒否、サンドボックス。鍵の載ったログを貼らない |
| コミット | 動作を確かめるため鍵を直書きし、そのまま残す。.env を加える。試験の値に本物の鍵を使う | .gitignore、コミットの前の検出、push protection |
| ログと出力 | デバッグの表示、env の出力、誤りの報告に載った接続文字列。CIのログ | 鍵を表示しない。CIの値を1つずつ秘密に登録する |
| 設定ファイル | MCPの接続や compose の設定に鍵を直書きし、設定と一緒にコミットする | 環境変数の参照にする |
- Claude Code は、利用者の指示とモデルの出力のすべてを提供元へ送る。手元では会話の記録を
~/.claude/projects/に平文で既定30日残す[1]。AIが読んだ鍵は、この2か所に入る。 - GitHub Actions のログは登録した秘密の値を伏せるが、値を変換した形は伏せられる保証が無い。複数の値を1つの JSON などにまとめず、値ごとに秘密に登録する[2]。
- CWE は、ソースへの直書きを CWE-798、ログへの書き出しを CWE-532 として扱う[3][4]。
置き場所
| 場面 | 置き場所 |
|---|---|
| 本番 | クラウドの秘密の管理の仕組みか、実行時に注入する環境変数。リポジトリにも、イメージにも焼き込まない |
| CI | CIの秘密の機能。クラウドへは OpenID Connect で入り、長く使う鍵を置かない[2] |
| 手元 | リポジトリの外か、無視の設定をしたファイル。AIの道具の読み取りを拒否する |
| 設定ファイル | 値ではなく変数の参照を書く |
.claude/settings.json 鍵のファイルを読ませない
{
"permissions": {
"deny": ["Read(./.env)", "Read(./.env.local)", "Read(./secrets/**)"]
}
}
この拒否は Read の道具と cat .env のような読む命令の両方に効くが、ファイルを開くスクリプトは止めない。OSの水準で止めるには、拒否の規則を引き継ぐサンドボックスを併せて使う[5]。
.mcp.json 値ではなく参照を書く
{
"mcpServers": {
"tickets": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer sk_live_9f3a..." }
"headers": { "Authorization": "Bearer ${TICKETS_TOKEN}" }
}
}
}
Claude Code は .mcp.json の command、args、env、url、headers で ${VAR} を展開する[6]。プロジェクトの .mcp.json はコミットされて共有される前提のファイルなので、値を書かない。
権限を最小にする
鍵が漏れたときの被害は、その鍵でできることの範囲で決まる。OWASP は、鍵には役目に要る最小の権限だけを付け、技術者が全部の鍵に触れる形にしないよう求める[7]。
- 用途ごとに別の鍵にする。AIの作業で使う鍵は、読み取りだけ、1つのリポジトリだけ、検証の環境だけ、のように絞る。
- 期限の短い資格情報を使う。OWASP は、アプリケーションを再起動しても、ビルドを終えても、発行済みの資格情報は無効にならないと注意している[7]。
- GitHub Actions の
GITHUB_TOKENは、要る権限だけを付け、要るジョブにだけ広げる[2]。
AWS は2025年7月23日、Amazon Q Developer の VS Code 拡張の1.84.0に悪いコードが入っていたと公表した。ビルドの設定にあった GitHub のトークンが要る範囲より広く、それを使った者が公開のリポジトリにコードを入れ、自動で配布物に含まれた。AWS によれば、そのコードは構文の誤りで動かず、サービスや利用者の環境に影響しなかった。AWS は資格情報を無効にして差し替え、コードを除き、1.85.0を出した[8]。広すぎるトークン1つが、AIの道具の配布物に手を入れる道になった例である。
漏れたときの順
- GitHub は、機密のデータが秘密の値なら、最初に無効化か差し替えをするよう書く。履歴を書き換えて強制 push しても、複製、fork、キャッシュされた表示に残り得る[9]。
- OWASP の手順も、漏れた鍵のすぐの無効化、新しい鍵の作成と配布、漏れた場所からの除去、鍵の発行と利用の記録による調査を並べる[7]。
- AIとの会話で鍵を読ませたときも、漏れとして扱う。会話の記録に残り、提供元へ送られている[1]。
GitHub の検出の仕組み
| 仕組み | すること | 限り |
|---|---|---|
| secret scanning | 全部のブランチの履歴、PRとディスカッションの本文とコメント、wiki を走査する。公開のリポジトリでは無料で自動。提携先の形式の鍵は提供元へ直接知らせる | 見つけるのは入った後。組織の非公開のリポジトリは GitHub Secret Protection が要る |
| push protection | 鍵を含む push を止める。利用者の側の保護は、公開のリポジトリへの push で既定で有効 | 書き込み権限があれば理由を付けて越えられる。越えた記録は警告と監査ログに残る |
出典は GitHub Docs[10][11]。手元のコミットの前で止めるなら、gitleaks や TruffleHog のような検出の道具を pre-commit に置く。OWASP も、コミットとPRの前の開発者の段階での検出を勧める[7]。
参照
- Data usage Anthropic
- Secure use reference GitHub Docs
- CWE-798 Use of Hard-coded Credentials MITRE
- CWE-532 Insertion of Sensitive Information into Log File MITRE
- Best practices for Claude Code Anthropic
- Connect Claude Code to tools via MCP Anthropic
- Secrets Management Cheat Sheet OWASP Cheat Sheet Series
- AWS-2025-015 Amazon Web Services、2025年7月23日
- Removing sensitive data from a repository GitHub Docs
- About secret scanning GitHub Docs
- About push protection GitHub Docs