秘密ファイルを AI に読ませない・書き換えさせない
やりたいこと
.env、credentials.json、~/.aws/ などを Claude Code に読ませたくない。うっかりコンテキストに入って会話ログに残るのを防ぎたい。
素朴にやると穴が空く
まず思いつくのはこれ。
// .claude/settings.json
{
"permissions": {
"deny": ["Read(.env)", "Read(secrets/**)"]
}
}
これでは3か所抜けます。
穴1: 書き込みは止まらない
Read の deny ルールは、同じパスへの Edit(新規作成を含む)も一緒にブロックします(v2.1.208 以降)。しかし Write と NotebookEdit は対象外です。
つまり読めないが上書きはできる状態になります。設定ファイルを壊される事故はこれで起きます。
穴2: サブプロセスからは素通り
Read / Edit の deny が効くのは、Claude の組み込みファイルツールと、Claude Code が中身を解釈できる Bash のファイルコマンド(cat、head、tail、sed など)だけです。
Python や Node のスクリプトがファイルを開く場合には適用されません。
# これは deny ルールを素通りする
python -c "print(open('.env').read())"
穴3: 広い allow が無効化されるほうの事故
評価順は deny → ask → allow で、ルールの具体度は順序を変えません。
Bash(aws *) を deny すると、より狭い Bash(aws s3 ls) の allow があってもブロックされます。安全側に倒れるので害は小さいですが、「allow を書いたのに動かない」の原因はたいていこれです。
手順
1. Read と Edit の両方を deny する
{
"permissions": {
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(secrets/**)",
"Read(**/*.pem)",
"Read(**/*.key)",
// 穴1 を塞ぐ。Write / NotebookEdit を止めるにはこちらが必要
"Edit(.env)",
"Edit(.env.*)",
"Edit(secrets/**)",
"Edit(**/*.pem)",
"Edit(**/*.key)"
]
}
}
Read(secrets/**) は、カレントディレクトリ配下の任意の深さにある secrets ディレクトリに一致します。トップレベルだけではありません。
symlink については、リンクのパスと解決先のどちらかが一致すれば deny が適用されます。抜け道にはなりません。
2. サブプロセス経由を塞ぐなら sandbox
穴2 は permission ルールでは塞げません。OS レベルで全プロセスをブロックするには sandbox を有効にする必要があります。
{
"sandbox": {
"enabled": true
}
}
Windows ネイティブの sandbox は非対応です(
facts/claude-code/sandboxing.md)。WSL を使うか、この穴が残ることを受け入れて運用する判断になります。
3. hook で代用しないこと
「PreToolUse hook で弾けばいい」と考えたくなりますが、推奨されません。
hook の Bash コマンド解析は、コマンドを解析できない場合に fail open(通す側に倒れる)します。if は best-effort であり、確実な許可・拒否には permission system を使うと明記されています。
hook は「ログを残す」「警告を出す」には向きますが、防御の最終線にはしないこと。
4. 組織で強制するなら managed settings
個人の .claude/settings.json はユーザーが編集できます。組織として外させたくない場合は managed settings で配布します。
- macOS:
com.anthropic.claudecodemanaged preferences ドメイン - Windows:
HKLM\SOFTWARE\Policies\ClaudeCode(HKCUはポリシー優先度が最低で、admin レベルのソースが無いときだけ使われる) - ファイル配布: システムディレクトリの
managed-settings.json
C:\ProgramData\ClaudeCode\managed-settings.jsonは v2.1.75 以降サポートされません。 古い手順書が残っていたら差し替えが必要です。
確認方法
設定したら実際に試して、想定どおり拒否されることを見てください。
# 1. 組み込みツール経由 — 拒否されるはず
# Claude に「.env を読んで」と頼む
# 2. Bash のファイルコマンド経由 — 拒否されるはず
cat .env
# 3. サブプロセス経由 — sandbox が無ければ通ってしまう
python -c "print(open('.env').read())"
3 が通る場合、穴2 が残っています。
なお、既知のツールに一致しない deny / ask ルールは起動時に警告が出ます。ツール名の綴りを間違えていないかはここで気づけます(_ や * を含む名前はチェック対象外)。
残る限界
- sandbox 無しではサブプロセス経由を止められない。 Windows ネイティブでは sandbox が使えない
- permission ルールは Claude Code の中の話。他のツールや人間の操作には効かない
- そもそも秘密情報をリポジトリに置かないのが本筋。これは緩和策であって解決策ではない
根拠
facts/claude-code/permissions.md— 評価順、deny の適用範囲、glob、symlinkfacts/claude-code/sandboxing.md— OS レベルのブロック、Windows 非対応facts/claude-code/hooks.md— fail open の挙動、permission system を使えという指示facts/claude-code/settings.md— managed settings の配布方法と優先順位