anthropics / anthropics/claude-code
Permission-denied message shows a sub-command excerpt of the Bash command, not the full command or the matching deny rule
- 主要言語
- Python
- スター
- 145k
- フォーク
- 23.1k
- PR マージ指標
- PR 指標を取得中
説明
## Summary
When a Bash tool call is blocked by a `permissions.deny` rule, the message returned to the model is
`Permission to use Bash with command has been denied.`, where `` is frequently **an excerpt**
of the command that was actually issued (a subset of the sub-commands split on `|`, `&&`, `;`, newlines),
and the message never names the deny rule that matched.
Two consequences observed over ~3 weeks of daily use (Claude Code 2.1.2xx, macOS, `permissions.defaultMode: "auto"`):
1. In 7 of 10 non-test denials, the displayed command was an excerpt. In 3 of those the excerpt *began* with
an unrelated sub-command (e.g. `head -10 …` or `tail -3 …`) while the sub-command that actually touched the
denied path came later in the pipeline. The model has no way to tell which sub-command triggered the denial.
2. In 2 cases the model (and the humans reading the transcript) misattributed the cause — once to "an execution-
environment classifier block", once to a PreToolUse hook — because the message gave no rule name. Both were
later traced to a user-level `Read(./)` deny rule being cross-applied to Bash.
## Environment
- Claude Code 2.1.260 (also reproduced on 2.1.2xx builds from mid-August 2026), macOS (arm64)
- User settings: `permissions.defaultMode: "auto"`; `permissions.deny` containing `Read(./.env)`, `Read(./.env.*)`,
`Edit(./.env)`, `Edit(./.env.*)` and, from 2026-08-22, `Bash(cat *.env*)`, `Bash(grep *.env*)`, etc.
- No managed settings; project settings contain only `hooks`.
## Minimal reproduction
1. In `~/.claude/settings.json` add `"permissions": {"deny": ["Read(./.env)"]}` and start Claude Code in a project
that contains a `.env` file.
2. Ask Claude to run a multi-stage Bash command whose *last* stage reads the file, e.g.
`sed -n '1,5p' README.md; echo "---"; grep -n "^FOO" .env | sed 's/=.*/=/'`.
3. Observe the tool result: `Permission to use Bash with command grep -n "^FOO" .env has been denied.`
— the `sed …`, `echo …` stages and the trailing `| sed …` are dropped, and the rule (`Read(./.env)`) is not named.
With a longer pipeline the excerpt can start at an unrelated stage.
## Expected
- The message should either quote the full command as issued, or clearly mark that it is an excerpt
(e.g. `… command (excerpt: sub-command 3 of 4) …`).
- The message should name the matching rule and its source file/level
(e.g. `denied by Read(./.env) in ~/.claude/settings.json`), the same way PreToolUse hooks can
identify themselves in their stderr text.
## Additional notes
- The documentation (`/docs/en/permissions`) states that Read/Edit deny rules also apply to "file commands Claude Code
recognizes in Bash, such as `cat`, `head`, `tail`, and `sed`". It does not say whether `grep`, `ls` or `stat` are
recognized. We observed one denial of `ls -la .env; stat -f "%Sm" .env` at a time when no Bash deny rule existed,
so at least `ls`/`stat` appear to be matched by the Read rule, but nothing in the message confirms this.
- Hook-based blocks (`exit 2` from a PreToolUse hook) are easy to attribute because the hook's own stderr text is
returned; deny-rule blocks are the only ones that are opaque.
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
調査の方向性
Reproduce the denial using the settings in ~/.claude/settings.json and the multi-stage Bash command from the issue, then read /docs/en/permissions to compare documented rule matching with the observed message. Trace the Bash permission-denial path and its message construction; done means the full command or a clearly marked excerpt is shown and the matching rule and source are identified.
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- bash, python
- 領域
- authorization, cli, security
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 活発
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 48/100