PowerShell(*) wildcard has silent carve-out for subexpressions -- bypasses allowlist, prompts anyway -- v2.1.119
Summary
The PowerShell(*) wildcard in settings.local.json does NOT actually cover all PowerShell commands as advertised. Any PowerShell command containing subexpressions ($(...)), script blocks ({}), or variable interpolation triggers a silent override labeled "Command contains subexpressions $()" or "Command contains script block that may execute arbitrary code" -- firing a permission prompt despite the explicit wildcard allow.
Environment
- OS: Windows
- Claude Code: v2.1.119
- settings.local.json contains:
"PowerShell(*)"in the allow array - Both desktop CLI and Remote Control exhibit the behavior
Expected behavior
PowerShell(*) in the allow array should cover ALL PowerShell commands, matching the advertised behavior and matching how Bash(*) works.
Actual behavior
PowerShell commands using common syntax patterns trigger a permission prompt regardless of the wildcard:
$()subexpressions -- extremely common in PowerShell (string interpolation, property access, arithmetic)${}variable expansion{...}script blocks (foreach bodies, try/catch, ForEach-Object, Where-Object)- Any command with a newline/multi-line structure
Real example that prompted today despite PowerShell(*) being allowed:
$procs = Get-Process python -ErrorAction SilentlyContinue
foreach ($p in $procs) {
try { $cmd = (Get-CimInstance Win32_Process -Filter "ProcessId=$($p.Id)").CommandLine } catch { $cmd='?' }
"PID $($p.Id): [$([int]($p.WorkingSet/1MB))MB]"
}
The warning shown is "Command contains subexpressions $()" with options "Yes / No" (no "Allow always" option), even though PowerShell(*) is already in the allow list.
Impact
This is the dominant failure mode for PowerShell permission gating in practice. Virtually every non-trivial PowerShell command uses subexpressions or script blocks -- they are not exotic patterns, they are the language's primary syntax. So PowerShell(*) as a wildcard is effectively useless except for the simplest one-liner cases like Get-Process.
For users on Windows who rely on PowerShell for monitoring, process management, and file operations, this means autonomous overnight operation is repeatedly interrupted for commands that SHOULD be covered by the explicit wildcard allow.
Reproduction
- Add
"PowerShell(*)"to settings.local.json allow array - Trigger any PowerShell tool call that uses
$()or{}syntax - Observe permission prompt still fires with "Command contains subexpressions" warning
Request
Either:
PowerShell(*)should genuinely cover all PowerShell commands including subexpressions (match Bash(*) behavior)- OR document that PowerShell(*) has carve-outs for subexpressions and provide a different syntax (e.g.,
PowerShell(*, allow_subexpressions)orPowerShell.Unrestricted(*)) to genuinely allow everything - OR add "Allow always" option to the subexpression prompt so users can explicitly override the carve-out
Related: #37442 (permission inheritance), #52898 (Remote Control ignores wildcards).
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗