Deny rules should match subcommands in pipes and compound commands

Resolved 💬 3 comments Opened Mar 31, 2026 by yellowbananaflask Closed Apr 4, 2026

Bug

Deny rules in permissions only pattern-match against the full command string, not against individual subcommands in piped or compound commands. This means a deny rule like Bash(rm *) is trivially bypassed:

Blocked (as expected)

rm -rf /foo

Not blocked (should be)

find /foo -type f | xargs rm
echo /foo | xargs rm -rf
cat files.txt | xargs rm
find /foo -exec rm {} \;
something && rm -rf /foo
something ; rm -rf /foo

Expected behavior

Deny rules should be evaluated against each segment of a piped/compound command, not just the full string. This is reportedly how allow rules already work — the docs state:

"Claude Code is aware of shell operators (like &&) so a prefix match rule like Bash(safe-cmd *) won't give it permission to run the command safe-cmd && other-cmd."

The same per-segment awareness should apply to deny rules. If rm appears as a subcommand in any segment of a pipe, &&, ||, or ; chain, and Bash(rm *) is in the deny list, it should be blocked.

Current workaround

Use broad wildcard patterns like Bash(* rm *) to catch rm anywhere in the command string. This works but is fragile and could false-positive on legitimate commands containing "rm" as a substring (e.g., grep "format" ...).

Environment

  • Claude Code CLI
  • macOS / zsh
  • settings.local.json permissions config

View original on GitHub ↗

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