[BUG] Respect `allowed-tools` when using combined / piped tool commands
Environment
- Platform (select one): Anthropic API
- Claude CLI version: 1.0.2
- Operating System: macOS 15.4.1
- Terminal: all
Bug Description
allowed-tools doesn't seem to be respected by commands combined by | && ;.
Steps to Reproduce
Here's a snippet of one section of my allowed-tools settings:
You can see I have nothing denied:
But none of these allowed tool permissions are honored if the command is combined (even if combining two allowed commands), nor will they allow me to accept the combination.
The end result is repeatedly approving benign tool usage that has already been allowed—chiefly "run tests and grep"
Expected Behavior
I absolutely understand and respect the security consideration of only honoring allowed-tools for commands without | && ; , but let me suggest:
- If a user has approved the initial command and the command used after the pipe, it should be allowed by default. It's completely surprising behavior otherwise. Similarly, if a user manually sets a pattern of
*it is reasonable to expect that means literally anything—and if that*ends at one of|&&;that should be clear when manually creating patterns. - Perhaps there should be a setting to explicitly enable honoring
allowed-toolsrules for combined/piped commands—if you see reasons that the specific combination is a unique attack vector. (Which is totally plausible; I haven't thought about it.) - In the absence of any of the above, we should specifically have patterns for combined commands.
Actual Behavior
Requires approval again for commands I have technically already approved.
Additional Context
This functionality is especially necessary in Claude 4 (and as Claude Code has seemed to have gained some better internal prompts for handling massive test runs by parsing them with greps), as Claude tends to run a lot more commands filtered by pipes.
Regarding the mention of security risks, tagging this #1106 as relevant here.
+1, still happening on Claude Code 1.0.3
It's pretty frustrating, specially when Claude is asked to validate API responses, It'll default to piping to jq and I'll have to approach every command.
I've had this issue from day one. For me it stops and asks every few minutes, which can get exhausting and annoying when you step away for a few minutes only to come back and see it did nothing because it was waiting for confirmation.
This should solve the problem for now:
https://github.com/BeehiveInnovations/ClaudeAutoResponder
Routinely encounter this, makes it hard to run tasks in the background (primary use case), as constant monitoring is required.
agree this is a huge pain. I don't like to run dangerous permissions but since opus pipes almost all bash commands it makes it required.
please fix
+1 still one of the most annoying bugs in claude code.
The Issue is More Complex Than Simple Pipe Detection. I've conducted further testing to better understand this issue, and the behavior is more nuanced than initially thought.
Test Case 1: Simple Pipeline (No approval required)
Prompt:
Execute the following processing in bash:
- Read package-lock.json
- Count the lines
Please write it as simply as possible in one line using bash pipe syntax.
Executed Code: `cat package-lock.json | wc -l` Result: ✅ No approval required
Test Case 2: Complex Pipeline (Approval required)
Prompt:
Execute the following processing in bash:
- Read package-lock.json
- Extract only lines containing \`version\`
- Count the lines
- Extract only numbers
- Sort the numbers
Please write it as simply as possible in one line using bash pipe syntax.
Executed Code: `cat package-lock.json | grep "version" | wc -l | tr -d ' ' | sort -n` Result: ❌ Approval required
Test Case 3: Custom Parser Approach (Still requires approval)
To isolate whether the pipe symbol itself was the issue, I created a custom parser to execute pipeline commands as separate steps:
Repository: https://github.com/pppp606/claude_run_pipeline_if_allowed/
Prompt:
Execute the following processing in bash:
- Read package-lock.json
- Extract only lines containing \`version\`
- Count the lines
- Extract only numbers
- Sort the numbers
Please write it as simply as possible in one line using bash pipe syntax.
Command:
node scripts/run_pipeline_if_allowed.js '[\"cat package-lock.json\", \"grep version\", \"wc -l\", \"grep -o \\\"[0-9]\\\\+\\\"\", \"sort -n\"]'
Result: ❌ Still requires approval
This custom implementation completely bypasses pipe syntax by:
- Parsing the command array
- Executing each command sequentially
- Piping output between commands programmatically
Updated Analysis: Command Category-Based Risk Assessment
Through systematic testing, I've identified that Claude Code's approval system appears to categorize commands by their functional capability rather than just complexity:
✅ Commands That Don't Require Approval:
- Display commands: `cat`, `echo`, `ls`, `pwd`
- Basic filtering: `head`, `tail`, `grep` (simple string matching)
- Counting: `wc`
- Simple 2-3 command pipelines using only the above
❌ Commands That Require Approval (Even in 2-command pipelines):
- Text transformation: `tr` (character translation)
- Text editing: `sed` (stream editor)
- Data manipulation: `sort`, `cut`, `uniq`, `awk`
- Advanced pattern extraction: `grep -o` (regex extraction)
Specific Test Results:
No Approval Required:
- `ls | wc -l`
- `cat package.json | head -5`
- `echo "hello" | grep "hello"`
- `ls | head -3 | wc -l`
Approval Required:
- `echo "hello" | tr 'a-z' 'A-Z'` (2 commands)
- `echo "hello" | sed 's/world/universe/'` (2 commands)
- `echo "3 1 2" | sort` (2 commands)
- `echo "123abc" | grep -o "[0-9]"` (2 commands)
- `echo "a,b,c" | cut -d',' -f2` (2 commands)
Key Findings
-
Command functionality matters more than pipeline length - Even 2-command pipelines require approval if they include text manipulation commands.
-
The system distinguishes between "safe" display/filtering operations and "risky" transformation operations - This suggests a sophisticated categorization system.
-
Common development tasks are affected - Basic text processing operations like sorting, field extraction, and regex matching require approval despite being low-risk.
Impact on Development Workflows
This conservative approach significantly impacts routine development tasks:
- JSON/log analysis with `jq` or `grep -o`
- Data formatting with `sort | uniq` combinations
- Configuration file editing with `sed`
- Field extraction with `cut` or `awk`
These operations pose minimal security risk but are essential for everyday development work.
Recommendation
The current categorization is overly restrictive for practical development use. Consider:
- Refined risk categories - Distinguish between data transformation (low risk) and system modification (high risk)
- Context-aware approval - Allow common development patterns without approval
- User-configurable thresholds - Let users adjust the sensitivity based on their security requirements
- Clear documentation - Provide explicit lists of which commands trigger approval
This bug also makes PreTool hook issues as well - sometimes even PreTool hook allowed command, it still trigger Claude UI.
This bug forces users to resort to --dangerously-skip-permissions.
The piped command permission issue has been resolved in v1.0.110. Commands like npm test | grep pattern now auto-approve when you have existing rules for both tools - no more repeated prompts for already-allowed commands.
Update to Claude Code v1.0.110+ to get the fix. Works automatically with your existing permission rules.
Thanks for reporting this!
@bogini wonderful! thank you.
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.