Windows execpolicy + PowerShell wrapping: safe delete rules are either bypassable or too noisy

Open 💬 2 comments Opened Mar 4, 2026 by offchan42

Windows execpolicy + PowerShell wrapping: safe delete rules are either bypassable or too noisy

I am reporting this because I tried to build a simple "prompt before delete" safety policy and ran into a reliability gap on Windows.

The short version:

  • direct delete rules work in simple cases
  • the same deletes can bypass rules when executed through pwsh -Command "..."
  • the only obvious workaround (prompt on all pwsh -Command) becomes noisy enough to block normal usage

I want to explain the reasoning and experiments clearly, step by step.

Goal and why it matters

Goal: always prompt before file deletion commands.

This matters even more if users consider danger-full-access. If delete protection can be bypassed by command shape, the policy is not trustworthy.

---

Step 1: baseline rule works (so far)

I started with direct delete rules:

prefix_rule(pattern=["Remove-Item"], decision="prompt")
prefix_rule(pattern=["del"], decision="prompt")
prefix_rule(pattern=["rm"], decision="prompt")

Reasoning: if the command token starts with Remove-Item (or del/rm), prompt should always trigger.

Check:

codex execpolicy check --pretty --rules .\default.rules Remove-Item .\tmp.txt

Observed result: prompt (expected).

At this point, the rule looked correct.

---

Step 2: hypothesis about wrapper execution

Then I asked: what if the same deletion is executed through PowerShell wrapper form?

pwsh.exe -Command "Remove-Item .\tmp.txt"

Why this hypothesis: agent tooling may execute commands through shell wrappers, not only as direct argv tokens.

Check:

codex execpolicy check --pretty --rules .\default.rules "C:\Program Files\PowerShell\7-preview\pwsh.exe" -Command "Remove-Item .\tmp.txt"

Observed result: no matched rules.

So the same deletion intent now escapes the delete rule, only because command shape changed.

This creates the core fear: a policy that appears safe in direct tests can still be bypassed in wrapped execution paths.

---

Step 3: attempted targeted fix for wrapper form

I tried to explicitly match wrapped deletes:

prefix_rule(
  pattern=["C:\\Program Files\\PowerShell\\7-preview\\pwsh.exe", "-Command", "Remove-Item"],
  decision="prompt"
)

Reasoning: this should catch pwsh -Command Remove-Item ....

But the match still fails when arguments are present, because the third token is the entire script string, for example:

"Remove-Item .\tmp.txt"

So "Remove-Item" does not match "Remove-Item .\tmp.txt" as a token prefix element.

In practice, exact full-string matching is too brittle (any argument or formatting change can miss).

---

Step 4: broad safety workaround, and why it breaks usability

Next idea:

prefix_rule(
  pattern=["C:\\Program Files\\PowerShell\\7-preview\\pwsh.exe", "-Command"],
  decision="prompt"
)

Reasoning: if we cannot reliably inspect script content, at least force approval on every wrapped command.

Expected: occasional prompt only when long wrapper commands are used.

Observed in my setup: this triggers for almost everything, so I get approval popups constantly.

So this workaround trades bypass risk for heavy daily friction.

---

Why this feels like an engine limitation

From these experiments, it looks like:

  • matching is exact token-prefix based
  • with pwsh -Command, the script body is treated as one opaque token

That combination makes it difficult to express a natural safety policy:

  • reliable prompt for destructive operations
  • low-noise operation for normal commands

---

Requested improvements (with concrete examples)

Any one of these would help:

  1. PowerShell-aware rule mode that parses -Command script safely.

Example intent:

powershell_command_rule(contains_cmdlet="Remove-Item", decision="prompt")
  1. Documented wildcard/regex for script token matching.

Example intent:

prefix_rule(
  pattern=["C:\\Program Files\\PowerShell\\7-preview\\pwsh.exe", "-Command", r"^Remove-Item(\s|$)"],
  decision="prompt"
)

---

Environment

  • OS: Windows
  • Shell: PowerShell (pwsh.exe)
  • Codex CLI: observed on 2026-03-05

View original on GitHub ↗

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