PowerShell tool: allow-listed commands (e.g. PowerShell(git *)) intermittently still prompt for permission
Bug description
On Windows, using the PowerShell tool exclusively (no Bash tool available in
this environment — checked, no Git Bash or WSL installed), broad allow
wildcards in settings.local.json like PowerShell(git *) andPowerShell(Select-String *) intermittently fail to suppress permission
prompts, even for commands that are plainly covered by them.
Repro
settings.local.json contains (among others):
{
"permissions": {
"allow": [
"PowerShell(git *)",
"PowerShell(Select-String *)",
"PowerShell(node *)",
"PowerShell(npm *)",
...
],
"defaultMode": "auto"
}
}
Running a plain pipeline built entirely from two allow-listed verbs still
produced a permission prompt:
git show master:path/to/File.vue | Select-String -n "editingId|editExternal"
This isn't an isolated case — the same session independently saw prompts for
plain node --test x > out.txt 2>&1 (no ;, no |) despite a node *
wildcard, across multiple turns.
What I found investigating this
I don't have visibility into Claude Code's internals, so this is inference
from observed behavior plus your own docs, not a confirmed root cause:
- Bash has documented wrapper-stripping before permission matching: a
fixed set of known wrappers (timeout, time, nice, nohup,
stdbuf, command, builtin) are stripped from a command before it's
matched against allow rules, so Bash(npm test *) correctly matches
timeout 30 npm test. I could not find an equivalent documented behavior
for the PowerShell tool.
- The PowerShell tool appears to wrap commands before execution. In
this same session, a PowerShell-native error (triggered by 2>&1 on a
git fetch) printed the At line:1 char:NNN context, and that context
showed text surrounding my literal command that I did not write — a
fragment resembling ...} catch {} } }; git fetch origin ... — implying
the string actually sent to powershell.exe has a preamble/wrapper
around the command I supplied via the tool's command parameter.
- Docs describe PowerShell rule matching as AST-based, splitting compound
commands on pipes/semicolons/&&/|| and matching each segment
independently. If permission matching runs against the wrapped string
rather than the raw command parameter, then a wrapper's own braces/
semicolons would appear as additional segments that don't match anything
in the allow-list — which would explain prompts on commands built
entirely from already-allowed verbs, including the pipeline repro above.
Ask
Could someone confirm whether:
- PowerShell tool calls get any wrapper/preamble applied before execution
(and if so, what it looks like), and
- whether permission-rule matching for the PowerShell tool operates on the
raw command string or on that wrapped version.
If wrapping does happen and isn't stripped before matching, applying the
same kind of wrapper-stripping Bash already has (or, more simply, matching
against the raw command string before any wrapping) would fix this for
PowerShell-only environments like mine, where there's no Bash tool to fall
back to.
Happy to provide full session logs/transcripts if useful.