正直に言うと、私はずっと貼ってきた
新しいAPIキーを取得すると、そのままChatに貼って動かす。
OpenAIで画像生成、Geminiで翻訳、Stripeのテスト。
多くの人が無自覚にやっている。私もそうだった。
ある日気づきました。チャットに貼った瞬間、そのキーは"ずっと残る"ことに。
何が起きるか
APIキーを1回チャットに貼ると、こうなります。
APIキーを1回貼ると起きること
ローカルの会話ログに残る
~/.claude/projects/
サーバーログにも記録される
Anthropic側・品質改善のため
再開時に再ロードされる
過去の会話を引き継ぐと
つまり、誤ってcommitしたキーと同じ重さで扱う必要がある。
「自分のローカルにしかないから大丈夫」じゃない。漏れたものとして対処すべき。
私の例:1日のヒヤリハット
ある日、Claudeに「OPENAI_API_KEYが設定されているか確認して」と頼みました。
書かれたコマンドはこれ。
echo "API key set: ${OPENAI_API_KEY:+yes}${OPENAI_API_KEY:-no}"
実行した瞬間、ターミナルに164文字のキー全文が表示された。
${VAR:-default} は変数があれば値そのものを返す仕様。「yes/no」のつもりが「値全部/no」になってた。
画面に出た瞬間、もう手遅れ。会話ログに残る。
そこから過去のClaude Code履歴を全部スキャンしたら、現役のGemini APIキーまで残っていました。「漏れてない」と思っていたものが、実は漏れていた。
安全な型を1つだけ覚える
これからは、原則を1つに絞ります。
APIキーをClaudeに見せない。AIには「環境変数を使うコードを書いて」と指示する。
APIキーの渡し方
差分は2行だけど、意味が全然違います。
AIが書くPythonコードは os.environ['OPENAI_API_KEY'] を読むだけなので、値はAIの目に触れない。
ステップ1:APIキーを ~/.zshrc に書く
ターミナルで:
open -e ~/.zshrc
末尾に追記:
export OPENAI_API_KEY=sk-proj-(ここに貼り付け)
export GEMINI_API_KEY=AIzaSy(ここに貼り付け)
保存(Cmd+S)→ ターミナルで反映:
source ~/.zshrc
これで全Pythonスクリプトが os.environ['OPENAI_API_KEY'] で読める。
ステップ2:Claudeにはコードだけ書かせる
「OpenAIで画像生成するスクリプトを書いて。
APIキーは OPENAI_API_KEY という環境変数に設定済み。」
Claudeが書くコードはこうなる:
from openai import OpenAI
client = OpenAI() # 環境変数を自動で読む
result = client.images.generate(...)
キー値はClaudeの目に入らない。会話ログにも残らない。安全。
ステップ3:環境変数の確認は値を出さないコマンドで
確認したいとき:
# 存在確認(値は出さない)
[ -n "$OPENAI_API_KEY" ] && echo "OK" || echo "NG"
# 識別したいなら部分表示
echo "先頭8文字: ${OPENAI_API_KEY:0:8}"
echo "長さ: ${#OPENAI_API_KEY}"
echo "$OPENAI_API_KEY" も printenv OPENAI_API_KEY も、もう書かない。
サンドボックスも「読み取り」までは守ってくれない
Claude Codeには /sandbox というOSレベルの隔離機能があります。有効にすると、書き込みは制限されます。ただし、読み取りは別です。
/sandbox が守る範囲
APIキー1つを環境変数で扱う分には、この型で足ります。ただし、複数のシークレットをまとめて守るには、読み取りを絞る追加設定が必要です。
自分の過去ログを棚卸ししてみる
過去のClaude Codeログにキーが残っていないか、自分でスキャンできる。
CLAUDE_DIR="$HOME/.claude/projects"
echo "OpenAI: $(grep -rho 'sk-proj-[A-Za-z0-9_-]*' $CLAUDE_DIR 2>/dev/null | awk 'length($0)>=40' | sort -u | wc -l) ユニーク値"
echo "Anthropic: $(grep -rho 'sk-ant-[A-Za-z0-9_-]*' $CLAUDE_DIR 2>/dev/null | awk 'length($0)>=40' | sort -u | wc -l) ユニーク値"
echo "Google: $(grep -rhoE 'AIza[A-Za-z0-9_-]{30,}' $CLAUDE_DIR 2>/dev/null | sort -u | wc -l) ユニーク値"
echo "GitHub: $(grep -rhoE 'gh[ps]_[A-Za-z0-9]{30,}' $CLAUDE_DIR 2>/dev/null | sort -u | wc -l) ユニーク値"
ヒットがあれば、それは「漏れていた」キー。
ヒットしたらどうするか
該当のサービスに行ってrotate(古いキーを無効化、新しいキーを作る)。
https://platform.openai.com/api-keys
https://aistudio.google.com/app/apikey
https://console.anthropic.com/settings/keys
https://github.com/settings/tokens
新しいキーを ~/.zshrc に書き直して source ~/.zshrc で反映。
もう使わないサービスなら、プロジェクトごと削除するのが一番きれい。
機密情報を扱うときも同じ構造
AIに個人や取引先を特定できる情報、業務の記録を扱わせるときも同じパターンになります。
社内システムの記録をチャットに貼って「まとめて」と頼む運用は、APIキーを貼るのと同じく危険。
機密情報を含むファイルを外部AIやAPIに読ませる処理も、チャットに貼るのと同じ「外に送る」扱いで考える。ファイル経由なら安全という意味ではない。
練習ではダミーデータか公開情報だけを使う。本番の機密データは、ローカル処理、社内承認済み環境、契約・監査済みの基盤など、所属先の情報管理ルールに従う。
セルフチェック
1. APIキーをClaudeのチャットに貼ると何が起きる?
2. ClaudeにAPIを使ったコードを書かせる安全な型は?
3. 環境変数の確認で書いてはいけないのは?
明日のアクション
3つやってみてください。
~/.zshrcを開いて、使っているAPIキーをexport OPENAI_API_KEY=...の形で書き込む(Claudeに直接は貼らない)source ~/.zshrcで反映、[ -n "$OPENAI_API_KEY" ] && echo OKで確認- 過去のClaude Code会話ログを
grep -rho 'sk-proj-[A-Za-z0-9_-]*' ~/.claude/projects/で棚卸し、ヒットしたら該当サービスでrotate