Bash permission matcher fails on compound shell constructs (pipes, subshells, heredocs)

Resolved 💬 3 comments Opened Mar 26, 2026 by afrancke Closed Mar 30, 2026

Description

Bash commands that start with patterns present in the allow list in settings.json still trigger permission prompts when the command contains compound shell constructs.

Reproduction

Given this settings.json allow list (abbreviated):

"allow": [
  "Bash(echo *)",
  "Bash(cat *)",
  "Bash(tail *)",
  "Bash(jq *)"
]

The following commands all prompt for permission despite starting with allowed patterns:

  1. Subshell expansions:

``
echo '{"ts":"'$(date -Iseconds)'","slug":"foo"}' >> /tmp/test.jsonl
`
Should match
Bash(echo *)` — prompts.

  1. Piped chains with semicolons:

``
cat /path/to/file.jsonl 2>/dev/null | tail -5; echo "---"; hostname -s
`
Should match
Bash(cat *)` — prompts.

  1. Heredoc syntax:

``
cat >> /path/to/file.jsonl << 'EOF'
{"key": "value"}
EOF
`
Should match
Bash(cat *)` — prompts.

  1. Variable-assignment prefixes:

``
TS=$(date -Iseconds) && cat >> /tmp/log.jsonl << EOF
{"ts": "$TS"}
EOF
`
Starts with a variable assignment so no pattern matches, but the actual command being run is
cat` which is allowed.

Expected behavior

If Bash(echo *) is in the allow list, any Bash command starting with echo followed by any arguments should auto-allow, regardless of shell metacharacters in the arguments.

Actual behavior

Commands prompt for confirmation even though they match the glob pattern.

Environment

  • Claude Code on macOS (Darwin 25.3.0)
  • Permission mode: Ask (not dangerous/bypass)

View original on GitHub ↗

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