anthropics / anthropics/claude-code
[BUG] Bash deny rules bypassed by any wrapper program outside ax()'s 8-item unwrap list
- Ngôn ngữ chính
- Python
- Star
- 145k
- Fork
- 23.1k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
## Summary
`permissions.deny` rules for Bash are matched against the program name of each
sub-command in the parsed AST. Before matching, Claude Code unwraps a **fixed,
eight-item list** of wrapper programs. Any other wrapper — an ordinary binary or
script on `PATH` that execs its arguments — shifts the program name, so no
`Bash( ...)` rule applies to the command underneath it. Deny and allow
rules alike are silently skipped.
This is not the env-var prefix case (#31558, closed) and not the command-chaining
case (#4956). Compound splitting works correctly. The hole is the wrapper
allowlist itself, and I could not find it named in any existing issue.
## Root cause
From `~/.local/share/claude/versions/2.1.258`, function `ax()`. The complete set
of wrappers it strips before rule matching:
```
timeout time nice stdbuf nohup command builtin noglob
```
plus leading `VAR=value` assignments. There is no fallback and no attempt to
resolve what an unknown wrapper actually executes.
## Reproduction
1. `permissions.deny`: `"Bash(git add -A*)"`
2. Ask for `git add -A` → correctly **denied**.
3. Ask for `git add -A` preceded by any wrapper binary on `PATH` that forwards
its arguments → **runs**. The deny rule is never consulted.
Compound forms are correctly caught, which shows the AST splitter is not the
problem: `cd ; git revert ...`, `rm -f ; git add -A ...`, and
`git add -A && git status` were all denied in the same environment.
## Observed impact
In one real session, `git add -A` was denied six times over several weeks. The
same operation then ran four times behind a wrapper, committing 103 unintended
files and 657,373 insertions to a working repository. The user had explicitly
configured that rule to prevent exactly this.
Denials: 2026-08-27T18:15:51Z, 2026-08-28T07:23:26Z, 07:42:37Z, 07:59:53Z,
09:35:12Z, 09:41:26Z.
Bypasses: 2026-09-06T16:57:28Z, 17:12:26Z, 18:44:10Z, 19:01:59Z.
## Why this is worth fixing even though deny rules are "best effort"
The documented position is that deny rules are client-side filtering, useful
against accidents rather than a determined bypass. This case is squarely the
accident it is meant to catch: no adversary, no prompt injection, no attempt to
evade. The wrapper was adopted for an unrelated reason and silently disabled
every git rule in the config.
Related, and relevant: #49874 recommends putting commands behind a wrapper
script specifically so allowlist matching stops seeing them. The same mechanism
that makes that workaround function is what defeats the deny list.
## Suggested direction
1. When the program of a sub-command is not a known wrapper and is not on
`PATH` as a resolvable non-wrapper, treat the command as **unmatched rather
than unmatchable** — i.e. escalate to a prompt instead of falling through.
2. Or: surface an explicit warning at config-load time that `Bash(...)` rules
only bind the literal program name and can be trivially shifted.
3. Or: check every token of a sub-command against deny rules, not only the
leading program.
At minimum, document the eight-item unwrap list. Users writing deny rules today
have no way to know it exists or how short it is.
## Environment
- Claude Code 2.1.258
- Linux
- Permission prompts suppressed for the session, so an unmatched command ran
silently rather than prompting. The bypass itself does not depend on that;
in a prompting session the same command would have asked instead of being
refused outright.
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Hướng nghiên cứu
Start by inspecting function ax() in ~/.local/share/claude/versions/2.1.258 and the Bash permission-matching path, then reproduce the behavior with a forwarding wrapper on PATH. The issue names no repository source files or tests; done should include an agreed handling direction and regression coverage showing that a wrapper cannot silently bypass Bash deny rules.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- bash
- Lĩnh vực
- cli, security
- Loại issue
- Lỗi
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Cần làm rõ
- Mức phù hợp với người mới
- 25/100