[BUG] "Always Allow" permission never matches compound Bash commands with quoted paths, pipes, and .exe on Windows
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Selecting "Always Allow" for a compound Bash command (quoted path with spaces + pipe + && + .exe) writes an entry to settings.local.json, but Claude Code continues to prompt for permission on every subsequent execution.
Command that triggers the issue:
"C:/Program Files/LLVM/bin/clang.exe" -std=c11 -Wall -g trigex.c -o trigex.exe 2>&1 | tail -5 && ./trigex.exe 2>&1
This command has multiple characteristics that likely each contribute to matching failure:
- Executable path contains spaces → must be quoted with double quotes
- Contains pipe operator (
|) and output redirection (2>&1) - Compound command chained with
&& - Uses
.exeextension on Windows
What Should Happen?
After selecting "Always Allow" once, the same command should be auto-approved on all future executions without prompting again.
Steps to Reproduce
- Ask Claude Code to run:
````
"C:/Program Files/LLVM/bin/clang.exe" -std=c11 -Wall -g trigex.c -o trigex.exe 2>&1 | tail -5 && ./trigex.exe 2>&1
- When prompted, select "Always Allow"
- Verify the permission was written to
.claude/settings.local.json - Ask Claude Code to run the exact same command again
- Observe: permission prompt appears again despite the entry in settings.local.json
Evidence
settings.local.jsonis updated after step 2 (the permission IS written — unlike #16762)- The written permission entry is likely the full literal command string (see #21845 for the pattern-vs-literal issue)
- The literal string fails to re-match on the next execution, presumably because:
- The
.exepath resolver expands the quoted path before pattern matching (#27537 hypothesis) - And/or the compound command (
|,&&,2>&1) is not parsed consistently between storage and matching
Related Issues
- #27537:
.exepattern matching fails on Windows (single command, no pipes tested) - #21845: Permission allow-list stores full literal commands instead of patterns (macOS)
- #16762: "Always Allow" not persisted to settings at all (different root cause — writing fails)
This report extends all three: on Windows, compound commands with a quoted .exe path and pipes are stored as literals (#21845 behavior), AND the .exe path-with-spaces matching fails (#27537 behavior), making it impossible to use "Always Allow" for any realistic compile-and-run workflow.
Error Messages/Logs
No error shown — Claude Code silently re-prompts without indication that the stored permission failed to match.
Claude Model
claude-sonnet-4-6
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.50 (Claude Code)
Platform
Anthropic API
Operating System
Windows 10 Pro (Build 10.0.19045)
Terminal/Shell
Windows Terminal / Git Bash (bash)
Additional Information
This is particularly disruptive for iterative development workflows (e.g., compile + run cycles) where the same compound command is executed many times per session. The only current workaround is manually approving every single invocation.
Showing cached comments. Read the full discussion on GitHub ↗
6 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Thank you for the triage! However, this issue is not a duplicate of the three listed:
vs #27537 (
Bash permission pattern fails to match commands with .exe extension):.execommand (e.g.,mytool.exe /arg). My issue involves a compound command combining a quoted path with spaces, pipe operator (|), output redirection (2>&1), and&&chaining — none of which are tested in #27537.vs #16561 (
Feature: Parse compound Bash commands and match each component against permissions):settings.local.jsonbut the entry never matches on subsequent executions — the user is never told the stored rule is ineffective.vs #25441 (
Bash permission wildcards don't match multiline/heredoc commands):|,&&, and2>&1with a quoted path containing spaces.The distinct failure scenario here is the combination:
&&.exeextension on WindowsEach factor alone may have a related issue; the combination causing silent write-then-fail is the new ground this issue covers.
Hooks bypass all the "Always Allow" pattern matching bugs (quoted paths, pipes, .exe on Windows):
The hook strips
.exeextensions, normalizes quotes, and usesbasenameto handle full paths — so"C:\Program Files\Git\bin\git.exe" statusmatches the same asgit status.Adding data from a multi-session workflow. We built a PermissionRequest hook that logs every permission prompt to a database.
35 prompts in 2 days for
source ../venv/bin/activate && python3 <script>across 3 concurrent sessions:| Session | Prompts | Period |
|---------|---------|--------|
| Session 1 | 26 | 1 day |
| Session 2 | 8 | 2 days |
| Session 3 | 1 | 1 day |
Both
Bash(source:*)andBash(python3:*)are in the allowlist. The approval does not persist within a session — the same exact command re-prompts multiple times in the same session.This is the most common compound command in our workflow (every test run, every research script). At 3 concurrent sessions, it's 10-15 unnecessary prompts per day.
Originally filed as #42563 — closing that as a duplicate of this issue.
Adding more reproduction cases from a systematic audit of 4 sessions (~200 allow patterns):
5. Command substitution (
$(...))Bash(echo *)is in the allow list.6. Long SSH with embedded heredoc
Bash(/c/Windows/System32/OpenSSH/ssh.exe *)is in the allow list. Confirmed in a brand-new session — not mid-session cache.7. Redirects on otherwise-allowed commands
All three base commands (
ls,git,stat) are in the allow list with*wildcard.Environment
acceptEditsmodeClosing my duplicate #43531 in favor of this issue.
Same here, but on Linux.
I can easily repro this.
Do you want us to debug this? I'm happy to work out a PR if you guys are even open to accepting any.