Windows execpolicy false positive when Start-Process and an unrelated URL appear in the same PowerShell script
What version of Codex CLI is running?
codex-cli 0.146.0
The failure was reproduced on 0.146.0. I also checked the latest stable release, 0.149.0, and the current main branch; both still contain the same relevant classifier logic described below.
What subscription do you have?
Pro
Which model were you using?
gpt-5.6-sol
What platform is your computer?
Microsoft Windows NT 10.0.26100.0 x64 (Windows 11 Professional)
What terminal emulator and version are you using (if applicable)?
Windows Terminal, PowerShell 7.6.3
Codex doctor report
The full report contains private local paths, so the relevant redacted fields are included below. All relevant runtime, config, auth, sandbox, and installation checks were OK; the overall warning was an unrelated update-status warning.
{
"schemaVersion": 1,
"overallStatus": "warning",
"codexVersion": "0.146.0",
"runtime": {
"platform": "windows-x86_64",
"installMethod": "npm"
},
"config": {
"model": "gpt-5.6-sol",
"modelProvider": "openai"
},
"system": {
"os": "Windows 10.0.26100 (Windows 11 Professional) [64-bit]"
},
"terminal": {
"terminal": "Windows Terminal",
"powershell": "7.6.3"
}
}
What issue are you seeing?
On Windows, execpolicy falsely classifies a benign compound PowerShell script as a dangerous URL launch when the script contains both:
- a local
Start-Processinvocation with no URL argument, and - an unrelated
Invoke-RestMethodcall to an HTTP URL later in the script.
With approval policy never, Codex rejects the command before PowerShell starts:
"C:\Program Files\PowerShell\7\pwsh.exe" -Command '...'
rejected: blocked by policy
The rejection is immediate (Wall time 0.0 seconds). Running the local Start-Process command by itself succeeds, and running the HTTP probe by itself succeeds. Combining them in one PowerShell script triggers the rejection.
This affects a common local-development pattern: start a local application or development server, then poll its loopback health/CDP endpoint until it is ready.
What steps can reproduce the bug?
- Run Codex on Windows with approvals disabled, for example:
``text``
codex -a never -s danger-full-access
- Ask Codex to execute this single PowerShell tool command:
``powershell
$process = Start-Process
-FilePath "$env:SystemRoot\System32\cmd.exe"
-ArgumentList @('/c', 'exit', '0')
-WindowStyle Hidden `
-PassThru
try {
Invoke-RestMethod
-Uri 'http://127.0.0.1:9/health'
-TimeoutSec 1
} catch {}
$process.Id
```
- Observe that Codex rejects the entire command with
rejected: blocked by policybeforepwsh.exeruns.
- Execute the
Start-Processportion and theInvoke-RestMethodportion as two separate Codex tool calls. Both are allowed, confirming that the combination is what triggers the false positive.
What is the expected behavior?
Execpolicy should only classify Start-Process as a dangerous URL/ShellExecute launch when an HTTP/HTTPS URL is an argument of that Start-Process invocation (or otherwise belongs to the same command expression).
An unrelated URL used by a separate Invoke-RestMethod command should not cause a local executable launch to be rejected.
The truly dangerous case must remain blocked:
Start-Process 'https://example.com'
Additional information
The apparent root cause is in is_dangerous_powershell_words. It computes has_url across the full flattened token list and independently checks whether any token contains start-process:
As a result, the URL and Start-Process token do not need to belong to the same command. The same implementation is still present on main:
When the heuristic marks the command dangerous and approval_policy is never, the decision becomes Forbidden:
https://github.com/openai/codex/blob/rust-v0.149.0/codex-rs/core/src/exec_policy.rs#L728-L741
A regression test could assert that this is not dangerous:
Start-Process local.exe; Invoke-RestMethod http://127.0.0.1:1234/health
while preserving the existing test that Start-Process 'https://example.com' is dangerous. A robust fix would associate URL arguments with the specific PowerShell command/AST node rather than scanning the whole script token set.
Related PowerShell execpolicy/parser reports, but not duplicates of this false positive:
1 Comment
Additional Windows desktop occurrence, observed on 2026-08-27. This appears closely related, with one variation: the unrelated HTTPS URL was an environment configuration value, not a health-probe URL.
Environment
sandbox_mode = "danger-full-access",approval_policy = "never".Observed operation
The user authorized an isolated loopback QA backend while preserving the existing development server and user data. One PowerShell tool invocation combined unused-port/non-existing-directory checks, isolated QA storage creation, process-local test environment assignments, and a local Python/Uvicorn launch with
Start-Process -WindowStyle Hiddenand redirected logs.Abbreviated, redacted command shape below. This is not a verified minimal reproduction: paths and the API-base value are placeholders; the original invocation also contained the checks and other assignments described above.
The URL was not an argument to Start-Process. It was child-backend configuration; no URL/ShellExecute launch was intended. No API key literal was present in the command.
Actual result
The entire tool invocation was rejected before PowerShell was created:
Explicit user re-authorization and repetition of the same launch request did not change the result. No QA runtime directory or QA listeners were created. The existing server was unchanged; frontend launch and browser acceptance tests were not attempted.
An additional diagnostic placed the original command in a single-quoted here-string and passed it as data to
codex execpolicy check --rules ... -- pwsh.exe -Command <command>. That outer tool invocation was also rejected before execution. This is not anexecpolicy checkverdict: the checker never ran and no matched-rule information was obtained.Successful controls and limits
git status, Python tests and production frontend builds succeeded in the same task; version-only CLI invocations also succeeded.Please check whether this is the same whole-script
Start-Process+ unrelated-URL heuristic in the desktop app-server version above. An actionable denial reason/rule identifier would help distinguish an intended restriction from a false positive without changing safety settings. Protection against actual URL/ShellExecute launches should remain intact.No private project name, username, real local path, credentials, customer data, full config file, or session transcript is included.