Skip to content

Restore cross-vendor Verifier B when openai/codex#32655 and #35871 are fixed (working invocation available now) #1740

Description

@kyle-sexton

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.execurrent 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:

  1. 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.
  2. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.priority: mediumReal value, no hard deadline; normal backlog flow.status: needs-decisionAwaiting a human or maintainer judgment call.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions