Claude Code で .env を読ませない deny 設定(Read ルールの書き方)
settings.json の permissions.deny に Read(./.env) を書いて Claude Code に .env を読ませない方法と、パターンごとの適用範囲、cat 経由の読み取りや deny が効かないケースまで解説します。
.env には API キーやデータベースのパスワードが入っています。Claude Code はワーキングディレクトリ内のファイル読み取りを確認なしで実行するため、放っておくと .env の中身がそのままモデルへの入力に含まれます。
これを止める確実な方法は、settings.json の permissions.deny に Read ルールを書くことです。deny ルールは allow より先に評価され、権限モードに関係なくブロックされます。
KEY POINT
この記事で分かること
.envを読ませない deny ルールの書き方- パターンの書き方によって適用範囲がどう変わるか
- deny が効かないケースと、その場合の対処
設定例:.env を deny に書く
プロジェクトの .claude/settings.json に次の内容を入れます。公式ドキュメントの「Example settings files」にある、チーム共有設定の例と同じ書き方です。
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)"
]
}
}
Read(./.env.*) は .env.local や .env.production のような派生ファイルを塞ぐためのものです。Read の deny ルールは Edit ツールと Write ツールにも適用されるので、この 3 行で読み取りと書き換えの両方が止まります。ただし NotebookEdit は対象外です。
用語解説
deny の優先順位: ルールは deny、ask、allow の順に評価され、最初に一致したものが結果を決めます。ルールの具体性は順序を変えません。ユーザー設定の allow とプロジェクト設定の deny がぶつかった場合も、deny が勝ちます。
パターンの書き方で適用範囲が変わる
Read と Edit のルールは gitignore と同じパターン記法を使います。先頭の記号によって、どこを起点に探すかが変わります。
| 書き方 | 起点 | 例 |
|---|---|---|
path / ./path | カレントディレクトリ | Read(./.env) |
/path | 設定ファイルの置き場所 | Read(/config/.env) |
~/path | ホームディレクトリ | Read(~/.aws/credentials) |
//path | ファイルシステムのルート | Read(//etc/shadow) |
深さの扱いも書き方で変わります。deny ルールでは次のようになります。
| deny ルール | ブロックするもの | ブロックしないもの |
|---|---|---|
Read(./.env) | カレントディレクトリの .env | サブディレクトリの .env |
Read(.env) または Read(**/.env) | カレントディレクトリ以下すべての .env | 親ディレクトリや別プロジェクトの .env |
Read(//**/.env) | ファイルシステム上のすべての .env | なし |
モノレポのように packages/api/.env と packages/web/.env が散らばる構成では、Read(./.env) では足りません。Read(.env) と書けば任意の深さに一致します。
ユーザー設定に書くときは起点が変わる
~/.claude/settings.json に Read(/secrets/**) と書くと、起点は設定ファイル側になり ~/.claude/secrets/** に一致します。プロジェクトの secrets ディレクトリには一致しません。すべてのプロジェクトに効かせるなら、// の絶対パスか ~/ のホーム相対パスを使ってください。
deny が効く範囲と効かない範囲
Read と Edit の deny ルールが適用されるのは、次の 3 つです。
- 組み込みのファイルツール(Read、Edit、Write など)。Grep や Glob、プロンプト内の
@file指定、IDE が共有する開いているファイルの情報にも、可能な範囲で適用されます。 - Claude Code が認識するファイル操作コマンド(
cat、head、tail、sedなど)。これらは通常は確認なしで実行されますが、deny ルールがあればブロックされます。 - Bash のリダイレクト先。
> fileと< fileが対象です。入力側のチェックは Claude Code v2.1.257 以降です。
シンボリックリンクはリンク自体と参照先の両方が照合され、どちらかが一致すればブロックされます。
スクリプト経由の読み取りは止まらない
deny ルールは、Python や Node のスクリプトが内部でファイルを開く場合には適用されません。python -c "print(open('.env').read())" のような形は、Claude Code から見ればただのコマンド実行です。プロセス単位で確実に遮断したい場合は、公式ドキュメントが案内しているとおりサンドボックスを有効にしてください。
なお、書き込みが自動承認されない protected paths の一覧に含まれるのは .envrc であって .env ではありません。しかも対象は書き込みだけです。読み取りを止めるには deny ルールを自分で書く必要があります。
設定が効いているか確認する
- 設定を保存し、Claude Code を起動します。
/permissionsを実行します。ルールの一覧と、それぞれがどの設定ファイル由来かが表示されます。- Claude に
.envを読むよう頼みます。File is covered by a Read deny rule in your permission settingsというエラーが出れば成功です。
ルールが照合対象にならない書き方の場合は、起動時に ... is not matched by file permission checks という警告が出ます。この警告が出たらパスの記法を見直してください。
allow / ask / deny 全体の設計は親記事の settings.json で permissions を設計する にまとめてあります。コマンド側を止める例は git push --force を禁止する deny 設定、ツールをまたいだ秘密情報の扱いは API キーや秘密情報を読ませないための設定 を参照してください。
まとめ
.claude/settings.jsonのpermissions.denyにRead(./.env)とRead(./.env.*)を書くReadの deny は Edit と Write にも効くが、NotebookEdit は対象外Read(./.env)はカレントディレクトリのみ、Read(.env)は任意の深さに一致する- deny は allow より優先され、bypassPermissions を含むすべてのモードで効く
- スクリプトが内部で開くファイルには効かないため、確実に遮断するならサンドボックスを使う
よくある質問
- deny を書けば cat .env でも読まれませんか?
- Read の deny ルールは、Claude Code が認識する cat・head・tail・sed などのファイル読み取りコマンドと、< file のリダイレクト先にも適用されます。ただし Python や Node のスクリプトが内部で開くファイルには適用されません。
- --dangerously-skip-permissions を付けても deny は効きますか?
- 効きます。公式ドキュメントには「deny ルールは bypassPermissions を含むすべてのモードでブロックする」と書かれています。逆に allow ルールは bypassPermissions では無効になります。
- .env は最初から保護されているのではないですか?
- 保護されていません。Claude Code の protected paths には .envrc は含まれますが .env は含まれず、しかも protected paths は書き込みだけが対象です。読み取りを止めるには deny ルールが必要です。
参考にした一次情報
この記事は公式ドキュメントを基に AI が下書きを作成し、運営者が内容を確認して公開しています。誤りを見つけた場合はお問い合わせからお知らせください。