Bash(*) wildcard in permissions.allow doesn't match all Bash commands
Description
Bash(*) in settings.json and settings.local.json permissions.allow does not prevent the user from being prompted to approve specific Bash commands. The user was prompted twice during a session despite having Bash(*) in both the project and local settings files.
Steps to Reproduce
- Add
"Bash(*)"topermissions.allowin both.claude/settings.json(project) and.claude/settings.local.json(local) - Run Bash commands like
echo '...',git add,time git commit -m '...', orrm -f .git/index.lock - User is prompted to approve despite the wildcard
Expected Behavior
Bash(*) should match all Bash tool invocations. No approval prompts should appear for any Bash command when this wildcard is in the allow list.
Actual Behavior
User was prompted to approve specific Bash commands. After approval, Claude Code added narrow session-scoped entries to settings.local.json:
"Bash(echo '# test file for bats skip verification')",
"Bash(git add:*)",
"Bash(time git commit -m ':*)",
"Bash(rm -f .git/index.lock)"
These are all already covered by Bash(*) which was present in the same file's allow list.
Environment
- Claude Code version: CLI (Opus 4.6, 1M context)
- OS: Windows 10 Home 10.0.19045
- Shell: bash (Git Bash)
- Settings merge order confirmed: user < project (settings.json) < local (settings.local.json)
Notes
Possible cause: the permission matcher may not be evaluating the Bash(*) wildcard pattern correctly for commands containing special characters (single quotes, colons, parentheses in the command string). The narrow entries CC auto-added use patterns like Bash(git add:*) which suggest the matcher is doing substring/prefix matching rather than glob evaluation against the full command.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗