
Claude Codeのpermissions設定、allowとdenyの優先順位を検証してみた
クラスメソッド株式会社データ事業本部所属のニューシロです。
前回の記事ではClaude CodeのCLAUDE.mdの禁止ルールとsettings.jsonのdenyルールの違いを検証しましたが、今回はその続編として、settings.jsonのallowとdenyの優先順位を検証してみました。
前回の記事: Claude CodeのCLAUDE.mdの禁止事項とsettings.jsonのdenyルールを検証してみた
前提
settings.jsonのpermissions設定とは
Claude Codeのsettings.jsonでは、permissionsフィールドでallow、deny、askの3種類のルールを設定できます。
{
"permissions": {
"allow": ["Bash(ls *)"],
"deny": ["Bash(rm *)"],
"ask": ["Bash(git *)"]
}
}
- allow: 確認なしで実行を許可する
- deny: 実行をブロックする
- ask: 実行のたびにユーザーに確認を求める
設定のスコープと優先順位
Claude Codeの設定には複数のスコープがあり、優先順位が定められています。
| 優先順位 | スコープ | 場所 | 説明 |
|---|---|---|---|
| 1(最高) | Managed | サーバー管理設定、plist / レジストリ、またはシステムレベルの managed-settings.json |
何によってもオーバーライドできない |
| 2 | コマンドライン引数 | CLIオプション | 一時的なセッションオーバーライド |
| 3 | Local | .claude/settings.local.json |
プロジェクトとユーザー設定をオーバーライド |
| 4 | Project | .claude/settings.json |
ユーザー設定をオーバーライド |
| 5(最低) | User | ~/.claude/settings.json |
他に何も設定を指定しない場合に適用 |
やりたいこと
以下の3点を検証します。
- allowとdenyで同じコマンドを指定した場合、denyが優先されるか?
- allowで広く許可し、denyでピンポイントに禁止した場合、正しく制御できるか?
- User設定(
~/.claude/settings.json)とProject設定(.claude/settings.json)で競合した場合、どちらが優先されるか?
公式ドキュメントによると、評価順序はdeny > ask > allowとされています。また、設定ファイルのスコープはProject設定がUser設定より優先されるとされています。これらが実際にその通りに動作するのかを確認します。
ルールは順序で評価されます。deny -> ask -> allow。最初にマッチしたルールが優先されるため、deny ルールは常に優先されます。
検証環境
前回と同様に、専用のディレクトリを用意して独立した環境で検証を行います。
poc/
├── CLAUDE.md
└── .claude/
└── settings.json
検証
検証1: allowとdenyが競合した場合、denyが優先されるか
settings.jsonに以下を設定します。同じパターンでallowとdenyの両方を指定します。
{
"permissions": {
"allow": ["Bash(ls *)"],
"deny": ["Bash(ls *)"]
}
}
この状態で「lsコマンドを実行してください」と指示します。

ドキュメントに記載された通り、allowよりもdenyが優先され、lsコマンドの実行が拒否されました。
(とはいえpoc/配下は表示してくれました)
検証2: allowで広く許可し、denyでピンポイントに禁止した場合
次に、lsコマンド全般をallowで許可しつつ、ls /etcだけをdenyで禁止する設定を試します。
{
"permissions": {
"allow": ["Bash(ls *)"],
"deny": ["Bash(ls /etc)"]
}
}
まず「lsコマンドを実行してください」と指示します。

こちらは実行してくれました。想定通りです。
次に「ls /etcを実行してください」と指示します。

こちらも想定通り、拒否してくれました。
denyルールの方が優先されていますので、このようなコマンドの制御方法もケースによっては有効だと思います。
検証3: User設定とProject設定が競合した場合
最後に、設定ファイルの配置場所による優先順位を検証します。
検証3a: User設定でallow、Project設定でdeny
User設定(~/.claude/settings.json)でlsコマンドをallowし、Project設定(.claude/settings.json)でlsコマンドをdenyした場合、どちらが優先されるかを確認します。
User設定(~/.claude/settings.json):
{
"permissions": {
"allow": ["Bash(ls *)"]
}
}
Project設定(.claude/settings.json):
{
"permissions": {
"deny": ["Bash(ls *)"]
}
}
この状態で「lsコマンドを実行してください」と指示します。

Project設定はUser設定より優先順位が高く、かつdenyがallowより優先されるため、Bashコマンドの実行が拒否されました。
こちらは想定通りの挙動でした。
検証3b: User設定でdeny、Project設定でallow
今度は逆に、User設定(~/.claude/settings.json)でlsコマンドをdenyし、Project設定(.claude/settings.json)でlsコマンドをallowした場合を確認します。
User設定(~/.claude/settings.json):
{
"permissions": {
"deny": ["Bash(ls *)"]
}
}
Project設定(.claude/settings.json):
{
"permissions": {
"allow": ["Bash(ls *)"]
}
}
この状態で「lsコマンドを実行してください」と指示します。

Project設定はUser設定より優先順位が高いですが、User設定に記載したdenyルールが無視されることはありませんでした。
denyルールはスコープの優先順位に関わらず、allowより優先されることが確認できました。
想定通りではありましたが、確認できてよかったです。
所感
結果は割と予想通りで、allowよりもdenyが優先されました(とはいえそうならないとセキュリティ上まずそうなのでよかったです)。
また、denyルールは、User設定・Project設定どちらに書いてあっても、スコープの優先順位に関わらずallowより優先されることも想定通りでした。
denyルールはスコープに関わらずallowより優先されるため、禁止したいコマンドはdenyに記載しておけばどのスコープでもブロックできそうです。この辺りの設定については、きちんと挙動を把握しておくことが大切そうですね。








