Bash permission glob matching breaks when command contains # character
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The Bash permission glob matcher treats # as a comment delimiter even when it appears inside quoted arguments. This causes commands that match an allow rule to still trigger a permission prompt if any argument contains #.
Minimal Reproduction
- Add this allow rule to
~/.claude/settings.json:
``json``
{
"permissions": {
"allow": [
"Bash(agent-slack search *)"
]
}
}
- Run a command without
#— auto-allowed, no prompt:
````
agent-slack search messages "test" --channel "fee-strategies" --limit 1
- Run the identical command with
#in a quoted argument — triggers permission prompt:
````
agent-slack search messages "test" --channel "#fee-strategies" --limit 1
The only difference between the two commands is "fee-strategies" vs "#fee-strategies". The first auto-allows; the second prompts.
What Should Happen?
# inside quoted strings should be treated as a literal character, not a comment delimiter. Both commands above match Bash(agent-slack search *) and should auto-allow.
Evidence from Session Logs
Analyzed two independent sessions (~180 JSONL lines total). Both show the exact same pattern:
| Phase | Commands | # in args | Permission prompted? |
|-------|----------|-------------|---------------------|
| Session 1, cmds 1–7 | agent-slack search/user/channel | No | No (auto-allowed) |
| Session 1, cmds 8–11 | agent-slack search ... --channel "#channel-name" | Yes | Yes |
| Session 2, cmds 1–7 | agent-slack search/user/channel | No | No (auto-allowed) |
| Session 2, cmds 8–12 | agent-slack search ... --channel "#channel-name" | Yes | Yes |
The transition from auto-allow to prompting happens precisely when # appears in arguments — not based on invocation count, parallelism, or subagent usage.
Likely Cause
The permission matcher appears to strip everything from # onward (treating it as a shell comment) before matching against the glob pattern, so the effective command becomes truncated and no longer matches.
Related Issues
- #31889 — wildcard permission matching not working (TFS paths with spaces — possibly different root cause)
- #29529 —
Bash(curl *)not matching (could be partially explained by#in URL fragments)
Claude Code Version
2.1.76
Platform
Anthropic API
Operating System
Linux (Arch, 6.19.6-zen1-1-zen)
Terminal/Shell
fish
This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗