Smarter contextual parsing of shell metacharacters before prompting for permission

Status Closed — not planned
Maintainer reply None cached
Activity 6 comments · opened Mar 13, 2026 · closed Apr 24, 2026

Problem

When Claude Code's Bash tool encounters shell metacharacters like >, |, ;, or #, it triggers a permission prompt with messages like:

"Command contains output redirection (>) which could write to arbitrary files"

This happens regardless of context — even when the usage is clearly safe. For example:

  • echo "hello" > /tmp/test.txt (known safe path)
  • Commands where # appears in a code comment, CSS hex color, or markdown heading
  • Simple pipes to well-known safe commands like | head, | wc -l

This creates unnecessary friction, especially for power users who are frequently approving obviously benign commands.

Proposed Solution

Instead of pattern-matching on the presence of a character alone, parse what follows the flagged character to assess actual risk:

  1. Output redirection (>): Check the target path. Writing to /tmp, a file in the current working directory, or a path the user has previously approved is far less risky than writing to /etc/passwd or ~/.ssh/authorized_keys.
  2. Pipes (|): A pipe to head, grep, wc, sort, jq, less, etc. is not dangerous. Only flag pipes to commands that can cause side effects (e.g., | sh, | bash, | tee /etc/...).
  3. Hash (#): Already discussed in other contexts — # in comments, hex colors, and markdown is not a shell risk.
  4. Semicolons (;): Evaluate the command after the semicolon with the same rules as a standalone command, rather than flagging the semicolon itself.

General principle: The permission system should evaluate the semantic risk of the full command, not just the presence of a metacharacter. A simple AST-level or tokenized parse of the shell command would catch the actually dangerous patterns while letting safe ones through.

Impact

  • Reduces permission prompt fatigue for experienced users
  • Prevents users from developing a habit of blindly approving prompts (which defeats the purpose of the security check)
  • Keeps the security model effective by focusing attention on genuinely risky commands

Alternatives Considered

  • Users can use dedicated tools (Write, Edit, Read) instead of shell commands, but sometimes shell is the right tool for the job
  • Allowlisting specific commands works but doesn't scale and requires manual configuration

View original on GitHub ↗

6 Comments

github-actions[bot] · 7 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/29085
  2. https://github.com/anthropics/claude-code/issues/16561
  3. https://github.com/anthropics/claude-code/issues/33340

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

matttennie · 7 months ago

This is related to the linked issues but not a duplicate. The overlap:

  • #16561 / #33340: Focus on compound/piped commands not matching existing permission rules — a permission matching problem.
  • #29085: Broader critique that the regex model has limitations — closer in spirit, but primarily about rules not sticking.

This issue proposes something different: contextual risk evaluation of metacharacters before prompting. Rather than just fixing whether tee matches a rule, the ask is that > /tmp/test.txt shouldn't trigger a prompt at all because the target path is inherently low-risk, and | head shouldn't prompt because head has no side effects. The distinction is prompt prevention via semantic analysis, not just better prompt matching via rule improvements.

Happy to consolidate if the team sees these as the same workstream, but the proposed solution here (AST-level parse → risk scoring before prompting) goes beyond what the other issues describe.

kaluchi · 6 months ago

Bug: # in quoted bash arguments triggers permission prompt, ignoring allow rules.

Repro:

jdt source "com.example.Foo#bar"

Prompts "This command requires approval" every time. # is inside quotes — not a shell comment. Allow rules (Bash(jdt *), Bash(jdt source:*)) do not prevent the prompt.

Workaround: PreToolUse hook:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "jq -r '.tool_input.command // \"\"' | grep -q '^jdt ' && echo '{ \"hookSpecificOutput\": { \"hookEventName\": \"PreToolUse\", \"permissionDecision\": \"allow\" } }' || true"
      }]
    }]
  }
}
github-actions[bot] · 5 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

kaluchi · 5 months ago

Up!!

github-actions[bot] · 5 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.