[BUG] Shell redirect target saved as standalone permission entry in settings.local.json
Bug Description
When a Bash command uses shell output redirect (> "filepath"), and the user clicks "Always allow", Claude Code saves the redirect target file path as a standalone permission entry in settings.local.json — instead of (or in addition to) the actual command pattern.
Reproduction
- Have
Bash(az:*)in globalsettings.json - Ask Claude to run a command with redirect, e.g.:
``bash``
az cognitiveservices account show --name my-resource --resource-group my-rg -o json 2>&1 > "D:/git/MyProject/infra/snapshot.json"
- When prompted, click "Yes, and don't ask again"
- Check
.claude/settings.local.json
Actual result
{
"permissions": {
"allow": [
"Bash(\"D:/git/MyProject/infra/snapshot.json\")"
]
}
}
The file path alone is saved as a permission — this is not a valid command and will never match anything.
Expected result
Either:
- No permission entry needed (the
azcommand is already covered byBash(az:*)) - Or save a meaningful pattern like
Bash(az cognitiveservices:*)
Additional context
This was observed across multiple commands with redirects (>, 2>&1 >). Multiple broken entries accumulated over sessions:
``json``
"Bash(\"D:/git/MyProject/infra/my-keyvault.json\")",
"Bash(\"D:/git/MyProject/infra/my-api.json\")",
"Bash(\"D:/git/MyProject/infra/my-cognitive.json\")",
"Bash(\"D:/git/MyProject/infra/my-storage.json\")"
All of these came from az ... -o json > "filepath" commands where Bash(az:*) was already in the global allow list.
Related issues
- #37106 — redirect (
2>&1) causes permission patterns to not match (same root cause area) - #19725 — "Always allow" stores entire command instead of extracting pattern (similar symptoms)
Environment
- Claude Code v2.1.81
- Windows 11 Pro (Git Bash)
- Permission patterns use
Bash(command:*)wildcard syntax
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗