Deny list patterns don't match commands with heredoc syntax

Resolved 💬 3 comments Opened Feb 5, 2026 by wuseal Closed Feb 9, 2026

Bug Description

Deny list patterns in .claude/settings.json do not match bash commands that use heredoc syntax (<< 'EOF'). The pattern matching appears to skip or handle heredoc commands differently.

Steps to Reproduce

  1. Add deny patterns to .claude/settings.json:
{
  "permissions": {
    "deny": [
      "Bash(cat*)",
      "Bash(cat >*)",
      "Bash(cat>*)",
      "Bash(*>*)"
    ]
  }
}
  1. Restart Claude Code session
  1. Try a simple cat command:
cat file.txt

Result: ✅ Blocked as expected - Permission to use Bash with command cat file.txt has been denied.

  1. Try cat with heredoc:
cat > file.txt << 'EOF'
content here
EOF

Result: ❌ Not blocked - command executes successfully

Expected Behavior

Both commands should be blocked since:

  • "Bash(cat*)" should match any command starting with cat
  • "Bash(*>*)" should match any command containing >

Actual Behavior

  • cat file.txt → Blocked ✅
  • cat > file.txt << 'EOF' → Not blocked ❌

Environment

  • macOS (Darwin 25.2.0)
  • Claude Code CLI

Additional Context

This affects users who want to enforce using dedicated tools (Write, Read, Edit) instead of bash commands for file operations. The heredoc syntax provides a way to bypass deny list rules.

Patterns tested that all fail to match heredoc commands:

  • "Bash(cat *)"
  • "Bash(cat*)"
  • "Bash(cat >*)"
  • "Bash(cat>*)"
  • "Bash(*>*)"

View original on GitHub ↗

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