「Read deny rule」エラーの対処 — Claude Code
Claude CodeのEdit・Writeが「Read deny rule」で止まる原因は、Readのdenyルールが同じパスのEditとWriteも塞ぐ仕様だからです。NotebookEditが対象外になる点も扱います。
.envやsecrets/をReadのdenyルールで守っているプロジェクトがあります。そのファイルをClaude Codeに編集させようとすると「File is covered by a Read deny rule」で止まります。原因は単純です。Readのdenyルールは、読み取りだけでなく同じパスのEditとWriteも一緒に塞ぐ仕様になっているためです。設定ミスではなく、意図された安全策として働いています。
File is covered by a Read deny ruleとは何のエラーか
表示される文言は次のとおりです。
File is covered by a Read deny rule in your permission settings and cannot be edited.Writeツールが拒否されたときは文末だけ変わり、and cannot be writtenになります。EditツールとWriteツールは、どちらも書き込んだ内容をClaude自身が読み返せる必要があります。読み取りそのものをReadのdenyルールで塞いでいる以上、書き込みだけを許すと「書いたのに読めない」という矛盾した状態になります。そのためClaude Codeは、ファイルへ一切アクセスする前に呼び出しごと拒否します。新規ファイルの作成であっても、そのパスがReadのdenyルールに一致すれば同じように弾かれます。
なぜReadのルール1つでEditとWriteの両方が止まるのか
多くの人が最初につまずくのはここです。「読み取りを禁止しただけなのに、なぜ編集まで止まるのか」という疑問は自然です。Claude Codeのパーミッションチェックは、ファイルツールとパスの対応がEdit(path)とRead(path)の2種類だけという設計になっています。WriteやNotebookEdit、MultiEdit向けにパスルールを書いても、Claude Codeはルールとして受理はするものの実際には参照しません。書くべきは常にEdit(docs/**)であり、Write(docs/**)ではないという点が、このエラーの背景にある設計です。
つまりReadのdenyルールは「読み取り拒否」と「編集拒否」の二役を1つのルールで兼ねています。ルールを2つに分けて書く必要はなく、Read(./secrets/**)と書いた時点で、そのパスへのEdit・Writeも自動的に塞がれます。
バージョンによる挙動の違い
このガードは段階的に強化されてきました。現在の挙動を前提に設定を組んでいると、古いバージョンでは想定どおりに動かないことがあります。
| バージョン | Editの扱い | Writeの扱い |
|---|---|---|
| v2.1.208より前 | Editの扱いReadのdenyルールでは止まらない(専用のEditdenyルールが必要) | Writeの扱い止まらない |
| v2.1.208以降 | Editの扱いReadのdenyルールで止まる | Writeの扱い止まらない |
| v2.1.228以降 | Editの扱いReadのdenyルールで止まる | Writeの扱いReadのdenyルールで止まる |
古いバージョンで「Readにdenyを書いたのにEditやWriteが通ってしまう」場合、まず疑うべきは設定ではなくバージョンです。claude updateで最新化するだけで、追加設定なしにガードが効くようになります。
NotebookEditだけは対象外
ReadのdenyルールがEdit・Writeを塞ぐ一方で、NotebookEditツールはこのガードの対象外です。Jupyter Notebook(.ipynb)を編集専用ツールで直接書き換える経路は、Readのdenyルールだけでは止まりません。ノートブックを含むディレクトリを本当に触らせたくない場合は、Readのdenyルールに加えてEditのdenyルールも同じパスへ足す必要があります。
対処法
状況によって、取るべき対応は2つに分かれます。
- Claudeに編集させたい場合:
/permissionsまたはsettings.jsonのpermissions.denyから、該当パスのReadルールを削除するか、範囲を狭める。プロジェクト全体を覆うRead(./secrets/**)のようなワイルドカードが原因になっていることが多く、必要な範囲だけに絞り込めば編集が通るようになります - ファイルには一切触らせたくない場合:
Readのdenyルールはそのまま残し、Editのdenyルールを同じパスに追加してNotebookEditの経路も塞ぐ
機密ファイルを守る設定は、公式ドキュメントが挙げているこの形が土台になります。
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./config/credentials.json)"
]
}
}このパターンで.envやsecrets/配下を保護すると、ファイル探索・検索結果からの除外、読み取り拒否、EditとWriteの拒否までを1つの設定でまとめて実現できます。
allowルールを書いても止まる理由
Edit: allowのような許可ルールを別途書いていても、このエラーは解消しません。Claude Codeのルール評価順序はdeny → ask → allowの順で固定されており、最初に一致したルールが結果を決めます。Bash(aws *)のような広いdenyルールは、より具体的なBash(aws s3 ls)のallowルールを上書きします。同じ関係が、ReadのdenyルールとEditのallowルールの間にも成り立ちます。denyルールは許可の例外を持てないため、Editを通したいなら許可を足すのではなく、denyルール自体を削るか狭める以外に道はありません。
WriteやGlobにパスルールを書いてしまう間違い
パーミッション設定でありがちな誤りが、Write(path)やGlob(path)にルールを直接書くパターンです。Claude Codeはこれらのルールを設定ファイルとしては受理しますが、ファイルアクセスの判定時には一切参照しません。起動時に警告が出るため気づく機会はありますが、警告を見落としたまま「ルールを書いたのに効かない」と誤解しやすいポイントです。対応表は次のとおりです。
| 書いてしまいがちなルール | 実際に書くべきルール |
|---|---|
Write(docs/**) | 実際に書くべきルールEdit(docs/**) |
NotebookEdit(docs/**) | 実際に書くべきルールEdit(docs/**) |
MultiEdit(docs/**)(レガシー) | 実際に書くべきルールEdit(docs/**) |
Glob(docs/**) | 実際に書くべきルールRead(docs/**) |
例外は--allowedTools経由で渡すGlobルールのみで、これだけはコマンドライン引数として機能します。設定ファイル(settings.json)に書くGlobルールは無効なままです。
旧ignorePatterns設定からの移行
機密ファイル除外の設定は、以前はignorePatternsというキーで書かれていました。現在のpermissions.denyはこの設定を置き換えたもので、書き方だけでなく効果範囲も広がっています。permissions.denyにReadルールを書くと、ファイル探索・検索結果からの除外に加えて読み取り拒否も実現します。さらに本記事のテーマであるEdit・Writeの拒否まで、1つの設定で一括して実現できます。古いignorePatternsをそのまま使っているプロジェクトを引き継いだ場合は、permissions.denyへの書き換えを検討する価値があります。
Bash経由のファイルアクセスとの違い
ReadとEditのdenyルールは、Claude Codeの組み込みファイルツールに適用されます。加えて、Bashで実行されるcat・head・tail・sedのような「Claude Codeが認識しているファイルコマンド」にも適用されます。ただし、Pythonスクリプトやnode.jsのプログラムが内部でファイルを開くような、任意のサブプロセス経由のアクセスまでは対象外です。OSレベルで全プロセスからのアクセスを止めたい場合は、denyルールではなくサンドボックスの設定が必要になります。
使い分け早見表
| やりたいこと | 設定 | 効果 |
|---|---|---|
| Claudeに読ませない | 設定Read(path)のみ | 効果読み取り・Edit・Write(v2.1.228以降)を拒否。NotebookEditは通る |
| Claudeに一切触らせない | 設定Read(path) + Edit(path) | 効果読み取り・Edit・Write・NotebookEditすべてを拒否 |
| 特定パスだけ範囲を狭める | 設定Read(./secrets/**)をより具体的なパスへ書き換え | 効果意図しない広範囲ブロックを避けられる |
| OSレベルで完全遮断 | 設定サンドボックス設定 | 効果任意のサブプロセス経由のアクセスも遮断 |
よくある質問
.gitignoreに書いたファイルは自動的に保護されますか
されません。.gitignoreはGitの追跡対象外を決めるだけで、Claude Codeのパーミッションとは無関係です。機密ファイルを守るにはpermissions.denyにReadのルールを明示的に書く必要があります。
既存ファイルの中身を書き換えず、末尾に追記だけしたい場合も止まりますか
止まります。Editツール・Writeツールは操作の種類にかかわらず、対象パスがReadのdenyルールに一致した時点でファイルへのアクセス自体を拒否します。追記か上書きかは判定に関係しません。
モノレポの一部のパッケージだけを保護できますか
できます。Readのdenyルールはグロブパターンを受け付けます。Read(packages/billing/**)のように特定のパッケージだけを指定すれば、他のパッケージには影響を与えずに保護できます。モノレポ全体に広いパターンをかけてしまうと、意図しないパッケージまでEditが止まってしまうため、保護したい範囲をパッケージ単位まで具体的に絞り込むのが安全です。
Readのdenyルールをユーザー設定(~/.claude/settings.json)に書いても効きますか
効きますが、パスの書き方に注意が必要です。ユーザー設定側のRead(/secrets/**)は~/.claude/secrets/**を指し、プロジェクト内のsecretsディレクトリは対象になりません。プロジェクトをまたいで効かせたいなら、//から始まる絶対パスか~/から始まるホーム相対パスで書きます。
symlink経由でファイルにアクセスされた場合はどうなりますか
denyルールはsymlink自体とその参照先の両方をチェックします。参照先が別のdenyルールに一致すれば、symlink側が許可パスに含まれていてもブロックされます。allowルールより厳格に働く点が非対称です。
PreToolUseフックで同じことはできませんか
できますが、性質が違います。PreToolUseフックはツール呼び出しごとに任意のスクリプトを走らせて動的に許可・拒否を判定する仕組みで、条件分岐や外部連携を組み込めます。一方Readのdenyルールは、パスパターンに対して静的に決まる単純な拒否です。CI設定ファイルや.git配下のような「常に触らせたくない」パスにはdenyルールで十分で、状況によって判断を変えたい場合だけフックを組み合わせます。なお、フックが"allow"を返しても、一致するdenyルールがあれば拒否が優先される点は共通しています。
まとめ
「File is covered by a Read deny rule」は、ReadのdenyルールがEditとWriteの両方を道連れに塞ぐ仕様上のエラーです。読み取り拒否のつもりで書いたルールが編集まで止めてしまう挙動を「不便」と感じるか「意図どおりの安全策」と捉えるかで、対応の方向は変わります。編集させたいならReadルールの範囲を狭め、逆に一切触らせたくないならEditルールを追加してNotebookEditの抜け道もふさぎます。v2.1.208未満やv2.1.228未満のバージョンでは挙動が異なるため、設定を見直す前にまずバージョンを確認しておくと切り分けが早くなります。パーミッション設計全体を見直すならClaude Codeセキュリティ・権限ガイドが参考になります。settings.jsonの書式を確認するならClaude Code settings.json完全ガイドも役立ちます。