Cross-vendor "Verifier B" — the Codex arm of the dual-verification contract in
plugins/knowledge/skills/docpage-digest/SKILL.md — ran degraded (same-vendor adversarial
refuter) for the whole opus-5-prompting-integration workstream because Codex could not read
files on Windows. This is the durable record of what is broken, what works today, and when the
workaround can be dropped.
Headline: Verifier B is restorable now, at Codex CLI 0.146.0, with no weakening of the sandbox
posture and no change to the sandbox configuration in ~/.codex/config.toml. Two
invocation-level workarounds are needed, one per upstream bug. Both can be dropped when the
upstream issues close.
Answers the open triage question in #1259 ("is this our packaging or upstream Codex?"):
entirely upstream. Both of that issue's stages — the unresolvable helper and the downstream
logon failure — trace to the single upstream bug openai/codex#32655.
That also corrects #1259's own reading of stage 2: CreateProcessWithLogonW failed: 2 is not a
missing or broken restricted-logon account. Per #32655 the command-runner helper is likewise
unresolvable, falls back to a bare filename, and that bare name cannot be found in the fresh
environment CreateProcessWithLogonW hands the restricted user — hence error 2.
The two upstream bugs
1. openai/codex#32655 — helper path resolution.
Helpers are resolved relative to the launch path's parent, so launched as
%LOCALAPPDATA%\Programs\OpenAI\Codex\bin\codex.exe the search lands in
Programs\OpenAI\Codex\, which has no codex-resources sibling:
windows sandbox: orchestrator_helper_launch_failed: setup refresh failed to launch helper:
helper=codex-windows-sandbox-setup.exe, cwd=…, log=…, error=program not found
Workaround: launch codex.exe from a path whose parent does have a codex-resources sibling —
either the release directory (~\.codex\packages\standalone\releases\<version>\bin) or
~\.codex\packages\standalone\current\bin, since the current junction points at the release
directory and current\codex-resources therefore resolves. Both verified.
2. openai/codex#35871 — MSIX shell resolution.
When the sandbox resolves pwsh to the Microsoft Store (MSIX) build under
C:\Program Files\WindowsApps\, Windows refuses to launch that packaged binary under the
sandbox's restricted token and the run dies with ERROR_ACCESS_DENIED. Removing the
WindowsApps entries from the PATH handed to codex makes the shell fall back to non-packaged
PowerShell 5.1.
Measured behaviour at 0.146.0
Nonce control throughout: a 128-bit CSPRNG value at a known line of a scratch file, with Codex
asked to return only that line's exact text, and a literal FILE_ACCESS_UNAVAILABLE if it cannot
read files. Independently reproduced by a second reviewer with their own nonce.
| launch path |
sandbox mode |
WindowsApps on PATH |
result |
| PATH junction |
elevated (default) |
yes |
fails — orchestrator_helper_launch_failed |
| PATH junction |
elevated (default) |
removed |
fails — orchestrator_helper_launch_failed |
| either |
unelevated |
yes |
fails — CreateProcessAsUserW, wrapped ERROR_ACCESS_DENIED |
| either |
unelevated |
removed |
succeeds — nonce returned verbatim |
| release dir bin |
elevated (default) |
yes |
fails — CreateProcessAsUserW failed: 5 (Access is denied.) |
| release dir bin |
elevated (default) |
removed |
succeeds — nonce returned verbatim |
current\bin |
elevated (default) |
removed |
succeeds — nonce returned verbatim |
Under unelevated the setup helper is not consulted, so the launch path is immaterial there.
The last three rows are the ones that matter: at the package path, the yes/removed pair shows
the PATH strip is independently necessary, and both workarounds together keep the elevated
backend.
Recommended invocation
Keep [windows] sandbox = "elevated" as configured. Invoke Codex as the cross-vendor verifier
with both workarounds applied:
- launch
codex.exe from ~\.codex\packages\standalone\current\bin\codex.exe — current is a
junction onto the active release directory, so current\codex-resources resolves and the
helper is found, whereas Programs\OpenAI\Codex\ has no codex-resources sibling — and
- strip
WindowsApps entries from the PATH handed to that process,
- then
codex exec -s read-only ....
-c 'windows.sandbox="unelevated"' (plus the same PATH strip) also produces a working read and is
a legitimate alternative. The two backends do differ, but not in the direction first assumed here.
Measured on this machine, single trial each:
| check |
unelevated |
elevated |
-s read-only blocks a write |
yes — patch rejected, file never created |
not separately tested |
read of ~/.codex/auth.json |
DENIED |
READABLE |
So -s read-only is genuinely enforced on the unelevated backend — an earlier draft of this issue
claimed it "may be silently ineffective there", which was wrong and is retracted. The
read-isolation result is also the reverse of the intuition that elevated is uniformly stricter:
elevated grants its sandbox principals read ACEs (visible in the sandbox log), which is plausibly
why a sensitive file stayed readable under it. These are one trial each and are not settled.
openai/codex#35871's comments separately report PowerShell dropping to ConstrainedLanguage mode
under unelevated, and note that "Restricted read-only access requires the elevated Windows sandbox
backend" — which appears to describe restricted-read tiering rather than -s read-only write
blocking.
The elevated recipe above is recommended because it keeps the backend the vendor documents as
recommended and the one this machine is already configured for — not because unelevated was shown
to be unsafe.
Correction to an earlier internal finding: we briefly concluded that CLI 0.146.0 had regressed
a workaround that worked on 0.145.0, and considered downgrading. That was wrong — shell resolution
was an uncontrolled variable across those comparisons and the apparent version difference was a
PATH confound. No downgrade is needed.
Trigger to close
Both of the following, re-checked with the same nonce-control probe:
openai/codex#32655 fixed — the helper resolves when codex is launched from the installed
PATH entry, so the launch-path workaround is no longer needed.
openai/codex#35871 fixed — the sandbox skips MSIX-packaged shells, so the WindowsApps
PATH strip is no longer needed.
When both hold, a bare codex exec -s read-only in default configuration returns the nonce, the
invocation wrapper described above is deleted, and this closes.
The degraded-verifier fallback in docpage-digest/SKILL.md (L174-177) stays regardless. It is
a permanent capability clause covering "not installed, sandbox-broken, quota", not a workaround
for this bug.
Operational notes
Observed during this investigation; recorded because they cost time, not as fully characterised
findings.
codex doctor's sandbox row is a config echo, not a liveness check. It printed
✓ sandbox restricted fs + restricted network · approval OnRequest alongside
✓ install consistent, in the same configuration in which every sandboxed command
failed. Do not use it as an automation gate — probe with a real command.
codex update failed from an agent shell (installer child died with Get-FileHash is not recognized) while running the official install.ps1 directly from a normal PowerShell session
worked. Looks like environment inheritance; observed once, not chased further.
- Version pointer is a junction chain, handy for A/B testing across versions:
Programs\OpenAI\Codex\bin → .codex\packages\standalone\current\bin → a release directory.
Repointing current switches versions; prior release packages stay cached.
- Elevated-mode sandbox accounts are installer-created. Local accounts
CodexSandboxOffline
and CodexSandboxOnline exist and the sandbox log shows read ACEs granted to them, including on
~/.claude.json. Not created by this investigation — openai/codex#35871 reports the same pair
on a different reporter's machine. Noted because it is a standing local privilege surface worth
understanding before anyone widens it.
Cross-vendor "Verifier B" — the Codex arm of the dual-verification contract in
plugins/knowledge/skills/docpage-digest/SKILL.md— ran degraded (same-vendor adversarialrefuter) for the whole
opus-5-prompting-integrationworkstream because Codex could not readfiles on Windows. This is the durable record of what is broken, what works today, and when the
workaround can be dropped.
Headline: Verifier B is restorable now, at Codex CLI 0.146.0, with no weakening of the sandbox
posture and no change to the sandbox configuration in
~/.codex/config.toml. Twoinvocation-level workarounds are needed, one per upstream bug. Both can be dropped when the
upstream issues close.
Answers the open triage question in #1259 ("is this our packaging or upstream Codex?"):
entirely upstream. Both of that issue's stages — the unresolvable helper and the downstream
logon failure — trace to the single upstream bug
openai/codex#32655.That also corrects #1259's own reading of stage 2:
CreateProcessWithLogonW failed: 2is not amissing or broken restricted-logon account. Per #32655 the command-runner helper is likewise
unresolvable, falls back to a bare filename, and that bare name cannot be found in the fresh
environment
CreateProcessWithLogonWhands the restricted user — hence error 2.The two upstream bugs
1.
openai/codex#32655— helper path resolution.Helpers are resolved relative to the launch path's parent, so launched as
%LOCALAPPDATA%\Programs\OpenAI\Codex\bin\codex.exethe search lands inPrograms\OpenAI\Codex\, which has nocodex-resourcessibling:Workaround: launch
codex.exefrom a path whose parent does have acodex-resourcessibling —either the release directory (
~\.codex\packages\standalone\releases\<version>\bin) or~\.codex\packages\standalone\current\bin, since thecurrentjunction points at the releasedirectory and
current\codex-resourcestherefore resolves. Both verified.2.
openai/codex#35871— MSIX shell resolution.When the sandbox resolves
pwshto the Microsoft Store (MSIX) build underC:\Program Files\WindowsApps\, Windows refuses to launch that packaged binary under thesandbox's restricted token and the run dies with
ERROR_ACCESS_DENIED. Removing theWindowsAppsentries from the PATH handed tocodexmakes the shell fall back to non-packagedPowerShell 5.1.
Measured behaviour at 0.146.0
Nonce control throughout: a 128-bit CSPRNG value at a known line of a scratch file, with Codex
asked to return only that line's exact text, and a literal
FILE_ACCESS_UNAVAILABLEif it cannotread files. Independently reproduced by a second reviewer with their own nonce.
WindowsAppson PATHorchestrator_helper_launch_failedorchestrator_helper_launch_failedunelevatedCreateProcessAsUserW, wrappedERROR_ACCESS_DENIEDunelevatedCreateProcessAsUserW failed: 5 (Access is denied.)current\binUnder
unelevatedthe setup helper is not consulted, so the launch path is immaterial there.The last three rows are the ones that matter: at the package path, the
yes/removedpair showsthe PATH strip is independently necessary, and both workarounds together keep the elevated
backend.
Recommended invocation
Keep
[windows] sandbox = "elevated"as configured. Invoke Codex as the cross-vendor verifierwith both workarounds applied:
codex.exefrom~\.codex\packages\standalone\current\bin\codex.exe—currentis ajunction onto the active release directory, so
current\codex-resourcesresolves and thehelper is found, whereas
Programs\OpenAI\Codex\has nocodex-resourcessibling — andWindowsAppsentries from thePATHhanded to that process,codex exec -s read-only ....-c 'windows.sandbox="unelevated"'(plus the same PATH strip) also produces a working read and isa legitimate alternative. The two backends do differ, but not in the direction first assumed here.
Measured on this machine, single trial each:
unelevatedelevated-s read-onlyblocks a write~/.codex/auth.jsonSo
-s read-onlyis genuinely enforced on the unelevated backend — an earlier draft of this issueclaimed it "may be silently ineffective there", which was wrong and is retracted. The
read-isolation result is also the reverse of the intuition that elevated is uniformly stricter:
elevated grants its sandbox principals read ACEs (visible in the sandbox log), which is plausibly
why a sensitive file stayed readable under it. These are one trial each and are not settled.
openai/codex#35871's comments separately report PowerShell dropping to ConstrainedLanguage modeunder unelevated, and note that "Restricted read-only access requires the elevated Windows sandbox
backend" — which appears to describe restricted-read tiering rather than
-s read-onlywriteblocking.
The elevated recipe above is recommended because it keeps the backend the vendor documents as
recommended and the one this machine is already configured for — not because unelevated was shown
to be unsafe.
Correction to an earlier internal finding: we briefly concluded that CLI 0.146.0 had regressed
a workaround that worked on 0.145.0, and considered downgrading. That was wrong — shell resolution
was an uncontrolled variable across those comparisons and the apparent version difference was a
PATH confound. No downgrade is needed.
Trigger to close
Both of the following, re-checked with the same nonce-control probe:
openai/codex#32655fixed — the helper resolves whencodexis launched from the installedPATH entry, so the launch-path workaround is no longer needed.
openai/codex#35871fixed — the sandbox skips MSIX-packaged shells, so theWindowsAppsPATH strip is no longer needed.
When both hold, a bare
codex exec -s read-onlyin default configuration returns the nonce, theinvocation wrapper described above is deleted, and this closes.
The degraded-verifier fallback in
docpage-digest/SKILL.md(L174-177) stays regardless. It isa permanent capability clause covering "not installed, sandbox-broken, quota", not a workaround
for this bug.
Operational notes
Observed during this investigation; recorded because they cost time, not as fully characterised
findings.
codex doctor's sandbox row is a config echo, not a liveness check. It printed✓ sandbox restricted fs + restricted network · approval OnRequestalongside✓ install consistent, in the same configuration in which every sandboxed commandfailed. Do not use it as an automation gate — probe with a real command.
codex updatefailed from an agent shell (installer child died withGet-FileHash is not recognized) while running the officialinstall.ps1directly from a normal PowerShell sessionworked. Looks like environment inheritance; observed once, not chased further.
Programs\OpenAI\Codex\bin→.codex\packages\standalone\current\bin→ a release directory.Repointing
currentswitches versions; prior release packages stay cached.CodexSandboxOfflineand
CodexSandboxOnlineexist and the sandbox log shows read ACEs granted to them, including on~/.claude.json. Not created by this investigation —openai/codex#35871reports the same pairon a different reporter's machine. Noted because it is a standing local privilege surface worth
understanding before anyone widens it.