Claude CodeのProtected pathsとCritical pathsの違い
Protected pathsは書き込みを、Critical pathsはrm・rmdirの削除だけを止めます。bypassPermissionsで挙動が逆転する理由と、auto modeの2分カウントダウンまで一次ソースで確認します。
Claude CodeにはProtected pathsとCritical pathsという、名前が紛らわしい2つの安全装置があります。Protected pathsは.gitや.claudeなど特定のファイル・ディレクトリへの書き込みを止めます。Critical pathsはファイルシステムのルートやホームディレクトリを狙ったrm・rmdirによる削除を止めます。対象が「書き込みか削除か」で分かれている点が最大の違いです。bypassPermissionsモードでは挙動まで逆転します。この記事では両者の判定基準とモードごとの挙動に加え、削除確認が2分で自動拒否される仕組みと、見落としやすいサンドボックス側の保護までを追います。権限モード全体の変遷はClaude Code権限モデルの変遷で扱っています。
Protected pathsとCritical pathsの根本的な違い
守る対象と検査する操作
Protected paths
.git、.claude、シェルの起動ファイルなど、名指しされたファイル・ディレクトリへの書き込みが対象です。Edit・Write・リダイレクトを含むBashコマンドが検査され、読み取りは対象外です。
Critical paths
ルート、ホームディレクトリ、作業ディレクトリとその親といった場所そのものが対象です。そこに向かうrm・rmdirだけを検査し、中身が何であってもrm -rf /やrm -rf ~は同じ扱いです。
Protected pathsの対象は固定されていて、書き換えられるとClaude Code自身の挙動や権限設定が変わるものに限られます。書き込みは細かい単位で、削除は広い単位で守る。この非対称性が、名前の似た2つの機能が別々に存在する理由です。
Protected pathsは特定ファイルの書き込みを検査する
Protected pathsに含まれるディレクトリは.git、.config/git、.vscode、.idea、.husky、.cargo、.devcontainer、.yarn、.mvn、そして.claudeです。Claude Code自身がgit worktreeを置く.claude/worktreesだけは除かれます。--plugin-dirで読み込んだディレクトリも対象です。mod(プラグイン)のコードはファイルが変わるたびにClaude Codeが再読み込みして実行するためです。ファイル側は.gitconfigや各シェルの起動ファイル(.bashrc、.zshrc等)、.npmrc、.mcp.json、.claude.jsonなどです。
Protected pathsの完全なリスト
ディレクトリ: .git / .config/git / .vscode / .idea / .husky / .cargo / .devcontainer / .yarn / .mvn
そのほか: .claude(.claude/worktreesを除く) / --plugin-dirで読み込んだディレクトリ
ファイル: .gitconfig .gitmodules / .bashrc .bash_profile .bash_login .bash_aliases .bash_logout .zshrc .zprofile .zshenv .zlogin .zlogout .profile .envrc / .npmrc .yarnrc .yarnrc.yml .pnp.cjs .pnp.loader.mjs .pnpmfile.cjs bunfig.toml .bunfig.toml / .bazelrc .bazelversion .bazeliskrc / .pre-commit-config.yaml lefthook.yml lefthook.yaml .lefthook.yml .lefthook.yaml / gradle-wrapper.properties maven-wrapper.properties / .devcontainer.json / .ripgreprc pyrightconfig.json / .mcp.json .claude.json
書き込みが止まるのはdefault・acceptEditsモードだけではありません。planモードでも、バイパス許可があるセッションを除けば同様にプロンプトが出るか、auto modeが使えるなら分類器に回されます。プロンプトなしで通るのはbypassPermissionsモードと、バイパス許可があるプランニングセッションです。
| モード | Protected pathsへの書き込み |
|---|---|
default / acceptEdits | Protected pathsへの書き込みプロンプトで確認 |
plan | Protected pathsへの書き込みバイパス許可があれば許可、無ければ分類器かプロンプト |
auto | Protected pathsへの書き込み分類器が判定 |
dontAsk | Protected pathsへの書き込み拒否 |
bypassPermissions | Protected pathsへの書き込み許可 |
シンボリックリンク経由の書き込みには追加の網がかかります。分類器へ回るモードでも、解決先がProtected pathsになる書き込みは、要求されたパス自体が保護対象でなければプロンプトになります。--restricted(v2.1.248以降)を付けたセッションでは、分類器がProtected pathsへの書き込みを承認できなくなります。v2.1.287のclaude --helpでは、このフラグは次の3つをするものと説明されています。Bashなどのコード実行ツールとWebFetchを外します。ユーザー・プロジェクト・ローカルの設定ファイルを無視します。bypassPermissionsも拒否します。
重要なのは、settings.jsonのpermissions.allowルールがこの判定を素通りできないことです。.claude/**をEdit許可ルールに登録していても、Protected pathsの安全確認はallowルールの評価より先に走ります。
{
"permissions": {
"allow": ["Edit(.claude/**)"]
}
}このルールを設定しても、プロンプトが出るモードでの扱いは変わりません。確認画面での逃げ道は、セッション限りの許可だけです。プロジェクトの.claude/では、次の選択肢が出ます。
Yes, and allow Claude to edit files in this project's .claude folder for this session
~/.claude/では末尾が「its ~/.claude folder for this session」になった同じ選択肢が出ます。選ぶと、そのセッションの間は該当フォルダへの書き込みが確認なしで通ります。
Critical pathsはrm・rmdirの削除だけを検査する
Critical pathsが対象にする「場所」は次の5種類です。
- ファイルシステムのルート
- ルート直下のトップレベルディレクトリ(
/usrや/etcなど) - ホームディレクトリ
- Windowsのドライブルートとその直下(
C:\やC:\Windows) - 作業ディレクトリとその親
追加の作業ディレクトリ(additionalDirectories)も対象になりますが、条件が1つ付きます。rm -rf <dir>/*のようにグロブで指定したときだけが対象で、ディレクトリそのものを指定したrm -rf <dir>は対象外です。
場所を直接書かなくても、変数が空になったときにルート削除へ化ける形は同じく対象です。
| 削除の書き方 | 例 | 対象になる理由 |
|---|---|---|
| 変数直下のグロブや末尾スラッシュ | 例rm -rf "$DIR"/* | 対象になる理由変数が空だとルートからの削除になる |
| 値のない位置パラメータ配下 | 例rm -rf "$1"/* | 対象になる理由同じくルートからの削除に展開される |
| 変数+トップレベル名 | 例rm -rf "$TMPDIR/mnt" | 対象になる理由変数が空だと/mntを消す |
$(pwd)などから代入した変数 | 例D=$(pwd); rm -rf "$D" | 対象になる理由作業ディレクトリやリポジトリルートを指しうる |
| コマンド置換の出力だけが対象(再帰削除) | 例rm -rf "$(pwd)" | 対象になる理由実行前に対象を確かめられない |
| 末尾にコマンド置換が付くパス | 例rm -rf ~/$(cmd) | 対象になる理由置換が空なら残るパス(ここではホーム)で判定する |
| バックスラッシュだけのターゲット | 例rm -rf "\\" | 対象になる理由Git Bashが現在ドライブのルートと読むため、全プラットフォームで検査する |
(rm -rf ~)のようなサブシェルや、sh -c・bash -cに渡したインラインスクリプトの中の削除も見つけます。ダブルクォートのスクリプトは、呼び出し側のシェルが先に変数を展開します。そのためfind . -name '*.tmp' -exec sh -c "rm -rf \"$1\"/*" _ {} \;は、一致のたびにルート削除として扱われます。シングルクォートで$1に実際の値を渡すsh -c 'rm -rf "$1"/*' _ {}は検出されません。
引っかかったコマンドは、変数を"${DIR:?}"/*のように空なら止まる形で守るか、リテラルのパスに書き換えると通ります。$HOMEのように普通は値が入っている変数の直下はリテラルのパスにします。D=$(pwd)で作った変数は"${D:?}"でも解除されないため、これもリテラルのパスにします。コマンド置換の出力だけを対象にした削除は、置換を先に単独で実行してから、出力されたリテラルのパスを削除します。置換出力のチェックだけを切る環境変数としてCLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT=1もあります。
削除コマンドがCritical pathsに当たったときの挙動は、書き込みへの安全確認とは別のルールで決まります。allowルールにマッチしていても、PreToolUseフックが"allow"を返していても、Critical pathsのrm・rmdir削除は承認されません。これはモデルの判断ミスに対するサーキットブレーカーとして設計されており、matchするdenyルールだけが例外的に効いて操作をブロックします。
| モード | Critical pathsの削除 |
|---|---|
default / acceptEdits | Critical pathsの削除プロンプトで確認 |
plan | Critical pathsの削除プロンプトで確認(バイパス許可が無く分類器がコマンドを見ている間はautoと同じ) |
auto | Critical pathsの削除ターミナルでは2分の期限付きプロンプト。それ以外の面では即拒否 |
dontAsk | Critical pathsの削除拒否 |
bypassPermissions | Critical pathsの削除ターミナルでは2分の期限付きプロンプト |
明示的なaskルールがマッチする場合は、auto modeでも期限なしのプロンプトが出ます。autoでは、分類器は既定でこの種の削除を審査しません。
auto modeとbypassPermissionsでは確認が2分で拒否される
autoとbypassPermissionsでは、Critical pathsの削除プロンプトに2分のカウントダウンが付きます(v2.1.281以降)。無人で回しているセッションが確認待ちで止まり続けないようにするための仕組みです。
Critical paths削除プロンプトの流れ
- 1
rm -rf ~のような削除をClaudeが試みる
ターミナルに確認プロンプトが出ます。
- 2
2分の間に応答しなければ拒否される
期限が切れると、Claude Codeはコマンドを拒否し、代わりに何をすべきかをClaudeに伝えます。何かキーを押すとカウントダウンが止まり、プロンプトは回答を待ち続けます。
- 3
3回続けて期限切れになると以降は即拒否になる
そのセッションでは、以降のCritical paths削除は確認なしで拒否されます。新しいメッセージを送ると数え直しです。
autoでは、ターミナルを出せない面だと待たずに即拒否されます。-pの非対話実行、Agent SDK、VS Code拡張のチャット、Desktopアプリがそうです。拒否の通知は、消したかった対象を報告して削除はユーザーに任せるようClaudeに伝えます。
版ごとの流れはこうです。v2.1.218で、危険なrmなどの確認ダイアログはauto modeの分類器が判定する形に移りました。v2.1.281で、2分待ってから拒否する期限付きプロンプトへ変わりました。
この挙動はCLAUDE_CODE_DISABLE_DANGEROUS_RM_TIMEOUT=1で切れます。切るとautoでは削除が分類器へ回り、bypassPermissionsのプロンプトは期限なしに戻ります。分類器そのものの判定基準はClaude Codeのauto mode分類器は何を止めているかで扱っています。
bypassPermissionsモードで挙動が逆転する
ここがProtected pathsとCritical pathsの違いが最もはっきり出る場面です。bypassPermissionsモードは権限プロンプトと安全確認を無効化し、Protected pathsへの書き込みも含めてツール呼び出しを即座に実行します。ところがProtected pathsと比べると、Critical pathsのrm・rmdir削除は、このモードでも引き続きプロンプトで確認されます。明示的なaskルールなども同様にプロンプトが残ります。PowerShellのRemove-Itemがルートやドライブルート、ホームなどのシステムパスを狙う場合は、どのモードでも確認なしで拒否されます。cmdのrd・rmdir・del・eraseも同じ扱いです。cmd側のチェックはv2.1.283以降のもので、CLAUDE_CODE_DISABLE_POWERSHELL_CMD_RM_DENY=1で切れます。Remove-Itemの判定パターンはPowerShell Remove-ItemがClaude Codeでブロックされる条件で具体的に扱っています。
書き込みは通す、削除だけは止める。同じ「最も緩いモード」の中で正反対の扱いを受けるのは、両者の設計目的が違うからです。Protected pathsは「うっかり自分の設定ファイルを書き換えてしまう」事故を防ぐもので、隔離されたコンテナやVM前提のbypassPermissionsではその心配が薄れます。一方Critical pathsは、ルートやホームを丸ごと消すような操作へのサーキットブレーカーです。隔離環境であっても取り返しがつかないため、最も信頼度の高いモードでも外れません。
bypassPermissionsが有効になるのは、次の2つの場合です。--dangerously-skip-permissionsフラグを付けたとき。または起動時にpermissions.defaultMode: "bypassPermissions"を設定したときです。起動時に有効化していないセッションの途中からは入れません。--allow-dangerously-skip-permissionsは、あとからbypassPermissionsを選べるようにするフラグです。v2.1.287のclaude --helpにはこの2つのフラグが並んで出ます。
サンドボックスにも別の保護パスリストがある
「protected paths」という言葉は、実はもう1か所で別の意味に使われています。Bashサンドボックスが持つ独自のprotected pathsです。権限システムのProtected pathsは「ツールを実行する前に承認するかどうか」を決めます。対してサンドボックスのprotected pathsは、書き込みが許可されたディレクトリの中で、すでに実行中のコマンドを対象にします。実行中のコマンドが自分に権限を与えたり、Claude Codeがサンドボックスの外で動かすフックやMCPサーバーを足したりできないようにするためのものです。
サンドボックス側のリストは4グループに分かれます。
- 作業ディレクトリとその上位にある
.claudeの設定ファイル群、.claude/skills・agents・commands・hooks、.mcp.json - 作業ディレクトリだけにあるシェル起動ファイル、
.gitconfig、.vscode・.idea、.git内のhooksとconfig - 作業ディレクトリをベアリポジトリに変えてしまう
HEAD・objects・refsなどのgit内部ファイル ~/.claude(またはCLAUDE_CONFIG_DIRの指す場所)の大半と、~/.claude.json・認証情報ストア
このリストはallowWriteエントリやEditのallowルールで上書きできません。外す方法はsandbox.filesystem.disabledでファイルシステム分離を丸ごと切ることだけです。LinuxとWSL2では、サンドボックス内のコマンド実行中に現れたトップレベルのHEADファイルやobjects・refsディレクトリが削除されます。保護対象の設定ファイルのパスにシンボリックリンクが現れた場合は、リンク先への書き込みも次のコマンドから拒否されます。
つまり、権限システムのProtected pathsをすり抜けてBashコマンドが実行されても、サンドボックスが有効なら二重のチェックが働きます。削除側の話では、サンドボックス有効時でも、Critical pathsに当たるrm・rmdirは通常の権限フローを通ります。
サンドボックスが動くのはmacOS・Linux・WSL2です。ネイティブWindowsではコマンドがサンドボックスなしで動きます。Windowsで削除を止めるのは、権限モード側のCritical pathsとRemove-Itemの専用チェックです。
実務でどちらを意識すればいいか
| やりたいこと | 関わる仕組み | 挙動 |
|---|---|---|
.claude/settings.jsonを編集させる | 関わる仕組みProtected paths | 挙動プロンプトが出るモードではallowルールでも素通りできない(autoは分類器判定、dontAskは拒否、bypassPermissionsは許可) |
| 作業ディレクトリごと削除するコマンドを避けたい | 関わる仕組みCritical paths | 挙動bypassPermissionsでもプロンプトで止まる |
| CI/CDのロックダウン環境で動かす | 関わる仕組み両方 | 挙動dontAskが両方を拒否するので最も安全 |
| コンテナ内で自律実行させたい | 関わる仕組み両方 | 挙動bypassPermissionsは書き込みは通すが削除確認は残る(無人なら2分で拒否) |
自動化ワークフローを組むときにこの表が効きます。.claude/配下を書き換えるスクリプトを自動承認したい場合、Protected pathsの仕組み上allowルールでは突破できません。プロンプトへの応答をPermissionRequestフックで自動化するか、その部分だけ手動運用に残すか、どちらかを選ぶことになります。Critical pathsの確認も、askで止まるモードでは同じフックが回答できます。
無人の自動実行では、削除側の癖が別の形で出ます。rm -rf "$BUILD_DIR"/*のように変数配下をグロブで消すクリーンアップスクリプトは、変数が正しく入っていてもCritical pathsとして止まります。"${BUILD_DIR:?}"/*の形にしておけば、変数が空のときはrmではなくシェルがエラーで止まり、この判定にも当たりません。
まとめ
書き込みで困ったらProtected paths、削除で止まったらCritical pathsと切り分ければ、どのモードで何が起きるかを表から引けます。無人で回す設定では、.claude/への書き込みはフックか手動に残し、削除は変数をガードした書き方に揃えておくと、2分の拒否で止まる場面を減らせます。
よくある質問
Protected pathsに.envは含まれますか
公式が挙げるProtected pathsのファイル一覧に.envは含まれていません。環境変数ファイルへの書き込みを防ぎたい場合は、permissions.denyにEdit(.env)のようなルールを別途追加する必要があります。