PowerShell(*) wildcard has silent carve-out for subexpressions -- bypasses allowlist, prompts anyway -- v2.1.119

Resolved 💬 6 comments Opened Apr 24, 2026 by ThatDragonOverThere Closed Jul 6, 2026

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

  1. Add "PowerShell(*)" to settings.local.json allow array
  2. Trigger any PowerShell tool call that uses $() or {} syntax
  3. 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) or PowerShell.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).

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗