Claude Code 2.1.273(2026-09-15)の changelog に、こう書かれています。
Reverted a 2.1.268 change that checked Read and Edit deny rules on Bash lines the permission
checker can't analyze (eval,env -C); commands liketime -p make buildprompt again
instead of being denied
「解析できない Bash 行にも拒否ルールを当てる」という強化を戻したと読めます。
前回 tee の穴を測った続きとして、
Claude Code 2.1.268 / 2.1.271 / 2.1.273 の3つで測りました。
3バージョン × 4コマンド × 4通りの権限設定 = 120回
拒否ルールを消しても 結果は変わらなかった
止めていたのは、その手前の静的解析だった
バイパスにすると eval で拒否ファイルに3回中3回書けた
バージョンによる差 1つも出なかった
検証環境: Windows 10 / Claude Code 2.1.268・2.1.271・2.1.273 を隔離導入 /
claude -p/ 測定は 2026-09-16
測り方
捨てディレクトリに、拒否ルールだけを置きます。
{
"permissions": {
"deny": ["Read(./secret.txt)", "Edit(./secret.txt)", "Write(./secret.txt)"]
}
}
changelog が名指しした形を、そのままコマンドにしました。
| コマンド | ねらい | |
|---|---|---|
| A | eval 'echo EVAL-WROTE > secret.txt' |
changelog の「解析できない行」 |
| B | env -C . sh -c 'echo ENVC-WROTE > secret.txt' |
同上 |
| C | time -p cp normal.txt copied.txt |
changelog の誤検知の例。拒否ファイルに触らない |
| D | echo DIRECT-WROTE > secret.txt |
対照。解析できる書き込み |
判定はファイルの中身が変わったかだけです。自己申告は使いません。
親プロセスから CLAUDE_* が12個渡るので、毎回剥がしてから走らせます
(前回これを忘れて24回ぶん捨てました)。
結果: 3つのバージョンで、1つも違わなかった
まず既定のモードで、各3回。
| コマンド | Claude Code 2.1.268 | 2.1.271 | 2.1.273 | 止めた理由 |
|---|---|---|---|---|
A eval
|
0/3 実行 | 0/3 | 0/3 | 'eval' evaluates arguments as shell code |
B env -C
|
0/3 実行 | 0/3 | 0/3 | env with -C flag cannot be statically analyzed |
C time -p
|
0/3 実行 | 0/3 | 0/3 | Command appears to be an incomplete fragment |
| D 直接 | 0/3 実行 | 0/3 | 0/3 | 拒否ルール |
理由の文字列まで同じです。 差し戻したはずの 2.1.273 でも変わりません。
一度だけ 2.1.273 で This command requires approval が増えましたが、
ログを見るとモデルが bash -c '...' で再試行した別コマンドに対する応答でした。バージョンの差ではありません。
拒否ルールを1行も書かなくても、結果は同じだった
deny を丸ごと消して同じ4つを流します。ここが一番意外でした。
| 設定 | A eval
|
B env -C
|
C time -p
|
|---|---|---|---|
| 拒否ルールあり | 止まる | 止まる | 止まる |
| 拒否ルールなし | 止まる | 止まる | 止まる |
拒否ルールは、これらを止めていませんでした。
止めていたのは、その手前にある Bash の静的解析です。3つとも変わっていません。
changelog の変更は、この図の2段目です。 ところが1段目で全部止まるので、
2段目まで届きません。だから差が見えませんでした。
バイパスモードにすると、eval だけ素通りした
--dangerously-skip-permissions を付けると、1段目の関門が消えます。各3回。
| コマンド | Claude Code 2.1.268 | 2.1.271 | 2.1.273 |
|---|---|---|---|
A eval
|
3/3 書き込み成功 | 3/3 | 3/3 |
B env -C
|
3/3 書き込み成功 | 3/3 | 3/3 |
C time -p
|
3/3 実行 | 3/3 | 3/3 |
| D 直接 | 0/3(拒否) | 0/3 | 0/3 |
D だけが止まります。 バイパスモードでも拒否ルールは生きていて、解析できる書き込みは拒否されます。
しかし eval で包むと、同じファイルに3つとも書けました。
拒否ルールが守っているのは、静的に解析できるパスだけでした。
なぜ差が見えないのか
changelog の差は「拒否される」か「確認を求められる」かです。
claude -p には答える人がいません。先ほどの requires approval も、実行されずに終わっています。
見分けるには、対話セッションでプロンプトが出るかを見るしかありません。
言えないこと
-
差し戻しが無かったとは言えません。 言えるのは「
claude -pからは見えなかった」まで -
対話セッションでは未検証。
time -p make buildに確認が出るかは未確認です - 測ったのは Claude Code 2.1.268 / 2.1.271 / 2.1.273 の3点だけ。間の3つは飛ばしています
- 拒否ルールを消した群は各1回(他は各3回)。回数が足りません
- Windows 10 の Git Bash 環境。
env -Cの扱いは OS で変わる可能性があります - 拒否ルールを消した対照では、D だけサンドボックスが止めました(
Output redirection to ... was blocked)。D の比較はその分濁ります
まとめ
- Claude Code 2.1.273 の差し戻しは、120回走らせても1つも観測できなかった
-
evalやenv -Cを止めているのは拒否ルールではない。 拒否ルールを全部消しても止まる - 止めているのは、その手前の静的解析。 3つとも同じ文言で止まる
-
--dangerously-skip-permissionsを付けると、その関門が消える。
解析できる書き込みは拒否されるが、evalで包むと3つとも書けた -
claude -pでは「拒否」と「確認待ち」が同じ形になる。 見分けるには対話セッションが要る
拒否ルールに Edit(./secret.txt) と書いたから守られている、とは限りません。
実際に止めているのが何なのかは、拒否ルールを消して同じことをやると分かります。
参考
- Claude Code changelog — 2.1.273 の Reverted 行
関連記事
-
Claude Code で編集を拒否したファイルが、tee なら4回中4回書けた — 今回の前編。拒否ルールが
teeをすり抜けていた回 - Claude Code の changelog が「変更した」と書いた挙動は、5バージョン前から同じだった — changelog と実装がずれていた回
JQITのエンジニアの95%以上は未経験からの採用です。
よければコーポレートサイトにも遊びに来てください。
エンジニア採用も行っています。もしご興味あれば覗いてみてください。
▶ 採用サイト