Bash(*) wildcard in permissions.allow doesn't match all Bash commands

Resolved 💬 3 comments Opened Apr 13, 2026 by dknipme2 Closed May 24, 2026

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

  1. Add "Bash(*)" to permissions.allow in both .claude/settings.json (project) and .claude/settings.local.json (local)
  2. Run Bash commands like echo '...', git add, time git commit -m '...', or rm -f .git/index.lock
  3. 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.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗