openai / openai/codex

Windows elevated sandbox: CreateProcessAsUserW denies launch (error 5), then fails with 'no such logon session' (1312) after registering the target MSIX package

Open
#38,410 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app-server bug CLI sandbox windows-os
Dominant language
Rust
Stars
125k
Forks
19.5k
PR merge metrics
PR metrics pending

Description

Windows sandbox: CreateProcessAsUserW fails launching Store-packaged PowerShell (error 5), then error 1312 after registering the package for the sandbox identity — same command never succeeds

Environment

  • codex-cli version: 0.144.5
  • OS: Windows 11 (Home edition)
  • Target executable under test:
    C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.4.0_x64__8wekyb3d8bbwe\pwsh.exe
    (Microsoft Store / MSIX-packaged PowerShell 7.6.4)
  • Sandbox mode: workspaceWrite, elevated Windows sandbox (codex sandbox setup --elevated --current-user)
  • App Server invoked via the documented JSON-RPC stdio protocol
    (initializeinitializedthread/startturn/start), using an
    independently-built, source-verified client that reproduces the exact
    documented handshake.

Summary

Every attempt to launch the elevated Windows sandbox's allowed in-root
command (Store-packaged pwsh.exe) fails before the child process is
created. The failure mode is stable, reproducible, and was narrowed across a
long diagnostic session (~17 independently-verified rounds) that ruled out
every plausible cause on our side:

  1. Initially: every attempt failed identically with
    windows sandbox: runner failed during SpawnChild: CreateProcessAsUserW failed: 5 (Access is denied.) — before a process ID was ever assigned
    (exitCode: -1, durationMs: 0, processId: null).
  2. After registering the target MSIX package for the sandbox identity
    (Add-AppxPackage -Register under the sandbox's own non-admin logon
    context — see "The one lead that changed anything" below), the error
    changed to CreateProcessAsUserW failed: 1312 (A specified logon session does not exist. It may already have been terminated.) — and has
    remained 1312 on every subsequent attempt, including after a clean
    reboot with no intervening logon activity on the sandbox account.

The command has never once succeeded. windowsSandbox/readiness reports
{"status":"ready"} throughout.

What we ruled out (with evidence)

  • General sandbox setup/readiness: windowsSandbox/readiness returns
    ready, not notConfigured/updateRequired.
  • Our own request shape: our client sends the documented restrictive
    policy exactly — workspaceWrite, one disposable writableRoots entry,
    networkAccess:false, excludeTmpdirEnvVar:true, excludeSlashTmp:true
    confirmed against the installed stable/experimental JSON schemas.
  • Missing/absent provisioning: the version-5 setup marker, encrypted
    credential artifact, CodexSandboxOffline/CodexSandboxOnline accounts,
    and CodexSandboxUsers group all exist and are correctly configured
    (created 2026-07-11, confirmed present in every later check).
  • Stale/drifted provisioning: re-running codex sandbox setup --elevated --current-user completed cleanly (exit 0, refreshed passwords/marker,
    persisted [windows] sandbox = "elevated") but did not change the
    failure.
  • Desktop/session lock state: reproduced with the interactive session
    confirmed Active/unlocked (WTS SessionFlags:1) immediately before and
    after the attempt.
  • Account privileges: an elevated, read-only LSA audit of BUILTIN\Users,
    Everyone, Authenticated Users, both sandbox accounts, and
    CodexSandboxUsers found no explicit deny rule and no
    SeAssignPrimaryTokenPrivilege/SeIncreaseQuotaPrivilege grant anywhere —
    but per Microsoft's own CreateProcessAsUserW documentation, a restricted
    token derived from the caller's own token (via CreateRestrictedToken,
    which is what the sandbox runner appears to do) is exempt from the usual
    SeAssignPrimaryTokenPrivilege requirement, and a genuinely missing
    privilege should surface as ERROR_PRIVILEGE_NOT_HELD (1314), not 5.
  • WinSta0 ACLs: the current-session interactive window station has a
    present, non-null DACL with 15 allow ACEs and zero deny ACEs; no explicit
    ACE for either sandbox account, but no deny either.
  • AppLocker / WDAC / Code Integrity: no configured AppLocker policy found
    across GP-registry, PolicyManager, MDM CSP, and rule-match surfaces; five
    enforced CI policies present, none with an active Store-enforcement
    option; 130 event-log queries around the exact failure timestamps found
    zero application-control or package-denial events.
  • The target binary itself: launched manually, outside the sandbox,
    under the normal interactive account — opens cleanly to an interactive
    PowerShell 7.6.4 prompt every time. The package is not corrupted.

The one lead that changed anything

An Get-AppxPackage -User <SID> query found the current interactive account
has the Microsoft.PowerShell package registered (Status: Ok), while
both sandbox accounts (CodexSandboxOffline, CodexSandboxOnline)
returned zero registered packages, despite the package being installed
system-wide and visible in WindowsApps. AppX/MSIX packages require
per-user registration even when the package files are shared on disk.

We registered the package for CodexSandboxOffline only, using a normal
(non-admin) process running under that account's own loaded profile
(CreateProcessWithLogonW(LOGON_WITH_PROFILE)Add-AppxPackage -MainPackage 'Microsoft.PowerShell_7.6.4.0_x64__8wekyb3d8bbwe' -Register -Confirm:$false -ErrorAction Stop). This succeeded cleanly (exit 0, package
count 0 → 1, Status: Ok, no drift in provisioning/marker/credential state).

Immediately after registration, the sandbox's failure mode changed from
error 5 to error 1312 — and this was confirmed stable, not a timing
artifact
: we re-ran the identical AC-19-equivalent attempt after a full
machine reboot (no CodexSandboxOffline logon since boot, profile confirmed
unloaded, LastLogon predating boot by ~51 minutes), and it still failed
with exactly the same CreateProcessAsUserW failed: 1312.

Interpretation (ours, not confirmed against your source)

This looks like a two-stage problem:

  1. Without package registration: the restricted-token launch of a
    Store-packaged executable is denied outright (error 5), independent of
    classic account rights/ACLs — plausibly because MSIX/AppX package
    activation involves additional security checks (package identity,
    app-container/capability requirements) beyond what a plain
    CreateRestrictedToken-derived token satisfies for an unregistered
    package under that identity.
  2. With package registration: launch now gets further, but fails with
    "no such logon session" — plausibly because the runner's own
    CreateProcessAsUserW call path expects (or references) a logon session
    for the sandbox identity that isn't actually established yet at that
    point in the sequence, on a cold/clean account state.

We were not able to go further without instrumenting the closed
codex-command-runner.exe binary at the exact CreateProcessAsUserW call
site — the SpawnChild stage confirms the runner has already completed its
own CreateProcessWithLogonW/pipe handshake by the time this fails, so the
denial is specific to the child-launch call itself, not the runner's own
startup.

Reproduction

  1. codex sandbox setup --elevated --current-user on a Windows 11 Home
    machine.
  2. Start an App Server session, turn/start with
    sandboxPolicy: {type: "workspaceWrite", writableRoots: [<any disposable folder>], networkAccess: false, excludeTmpdirEnvVar: true, excludeSlashTmp: true}.
  3. Ask the model to run one command via exec_command/the default shell
    that writes a marker file inside the writable root (any simple PowerShell
    one-liner).
  4. Observe the commandExecution item report status: "failed",
    exitCode: -1, durationMs: 0, processId: null, and
    windows sandbox: runner failed during SpawnChild: CreateProcessAsUserW failed: 5 (Access is denied.).
  5. Register the Store PowerShell package for the sandbox identity
    (CodexSandboxOffline by default under networkAccess:false) and repeat
    step 3 — observe the error change to
    CreateProcessAsUserW failed: 1312 (A specified logon session does not exist. It may already have been terminated.).

What would help us most

  • Confirmation of whether Codex's own setup flow (codex sandbox setup --elevated) is expected to register any packages the sandboxed
    environment needs for the sandbox identities, and if so, why that
    didn't happen for PowerShell itself.
  • Instrumentation or a debug build that logs the exact access check and
    logon-session reference codex-command-runner.exe uses immediately before
    the failing CreateProcessAsUserW call, so we can tell whether it's
    looking for a pre-existing session that's supposed to be created
    elsewhere in the sequence.
  • Does the elevated Windows sandbox require Windows Pro/Enterprise? This
    machine is Windows 11 Home. We couldn't find anything in the public docs
    or the parts of codex-rs we reviewed suggesting an edition dependency —
    every API involved (CreateProcessAsUserW, CreateRestrictedToken, local
    account/window-station management) is available on Home — but we haven't
    been able to test on a Pro machine to rule it out empirically, and it
    would save everyone time if this is a known requirement.

Happy to provide the full evidence trail (source citations, exact
request/response transcripts with hashes, LSA/WinSta0/AppLocker audit
output) on request — trimmed here for length.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Windows sandbox setup flow and SpawnChild path in codex-rs, then inspect how codex-command-runner.exe reaches CreateProcessAsUserW after its CreateProcessWithLogonW/pipe handshake. Reproduce the documented JSON-RPC sequence and compare error 5 before package registration with 1312 afterward. Done means identifying whether setup should register packages or the launch path must establish the required logon session.

Written by the indexing model from the issue text.

Assessment

Tech stack
powershell, rust
Domain
operating-systems, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.