Windows sandbox setup marker ACL prevents Codex from starting sandbox after UAC setup
What happened?
After installing/reinstalling Codex for Windows, every normal sandbox command repeatedly triggered UAC and then failed with:
windows sandbox: orchestrator_helper_incomplete: setup helper exited successfully before setup completed
The sandbox setup helper itself appeared to complete successfully, but Codex kept treating setup as incomplete:
sandbox setup required: sandbox setup marker missing or incompatible
codex-windows-sandbox-setup.exe] setup binary completed
read-acl-only mode: applying read ACLs
read ACL run completed
The root cause on this machine appears to be the ACL on:
%USERPROFILE%\.codex\.sandbox\setup_marker.json
The file existed and contained a valid-looking marker, but the normal Codex process could not use it until the current Windows user was explicitly granted access. After granting the current user full control on setup_marker.json, normal sandbox commands started working immediately and no longer triggered UAC.
Environment
Codex Windows package: OpenAI.Codex_26.623.5546.0_x64__2p2nqsd0c76g0
Codex executable path: C:\Program Files\WindowsApps\OpenAI.Codex_26.623.5546.0_x64__2p2nqsd0c76g0\app\resources\codex.exe
PowerShell: 5.1.26100.8737
OS: Windows, build 26100 series
Marker file contents after permission was manually fixed
{
"version": 5,
"offline_username": "CodexSandboxOffline",
"online_username": "CodexSandboxOnline",
"created_at": "2026-06-28T11:57:37.952492200+00:00",
"proxy_ports": [],
"allow_local_binding": false,
"read_roots": [],
"write_roots": []
}
Observed behavior
- Run a normal command from Codex on Windows.
- UAC prompts for
codex-windows-sandbox-setup.exefrom the Codex WindowsApps package. - User approves UAC.
- Setup log says the helper completed.
- Codex still fails with
orchestrator_helper_incompleteand continues to reportsetup_marker.jsonas missing or incompatible. - The cycle repeats on subsequent commands.
Workaround
Granting the current Windows user access to the marker file fixed the issue:
icacls "$env:USERPROFILE\.codex\.sandbox\setup_marker.json" /grant "$env:USERDOMAIN\$env:USERNAME:F"
After that, normal sandbox commands succeeded without additional UAC prompts.
Expected behavior
The Windows sandbox setup helper should create setup_marker.json with ACLs that allow the normal Codex process to read/validate it after UAC-approved setup completes. If the marker exists but is unreadable, Codex should surface a clearer ACL/permission error instead of treating it as missing or incompatible.
11 Comments
Additional update: this is not limited to first install/reinstall. The issue reproduced later during
setup refresh.Observed later sequence:
At that point
%USERPROFILE%\.codex\.sandbox\setup_marker.jsonhad just been updated by setup refresh, but attempts to read it failed again withAccess is denied.Reapplying the same workaround restored normal command execution again:
After that, a normal sandbox command succeeded without UAC:
So the ACL regression appears to recur whenever setup refresh rewrites or updates the marker, not only during initial setup.
Confirmed on the current ChatGPT Windows desktop app (formerly Codex Desktop) on 2026-07-10.
I experienced the same behavior:
codex-windows-sandbox-setup.exe%USERPROFILE%\.codex\.sandbox\setup_marker.jsonexistedsandbox.logrepeatedly showedsetup binary completedsetup_error.jsonConfirmed with a little more detail on a current build.
Environment:
In this case the ACL written for
%USERPROFILE%\.codex\.sandbox\setup_marker.jsoncontained the machine/domain SID without the current user's RID. Redacted example: the ACE ended in...3867147518, while the current user SID ended in...3867147518-1001.icaclstherefore displayed a bare machine/domain identity rather thanCOMPUTER\user.That matches the observed behavior: the elevated setup process could create/update the marker, but the unelevated Codex process could not read it. Codex then reported both:
All logged OS setup steps (sandbox users, WFP rules, firewall rules, etc.) had succeeded, so this was not caused by the Insider build failing an OS prerequisite.
Granting the real current account access fixed it immediately:
After that,
codex sandbox cmd /c "echo SANDBOX_OK"returnedSANDBOX_OK, the UAC loop stopped, and normal sandbox commands worked after restarting the app.The ACL problem can recur when another sandbox setup/refresh path rewrites the marker. In a later attempt, a sandbox-backed helper again failed with
orchestrator_helper_incomplete; the marker still existed, but an unelevatedGet-Aclfailed withUnauthorizedAccessException. So the eventual fix likely needs to preserve/grant the current user's RID on every marker rewrite, not only during initial installation.Follow-up with three additional findings from the same machine, which may help narrow down where the fix needs to go:
1. The truncated-SID ACE is not limited to
setup_marker.json.The parent directory
%USERPROFILE%\.codex\.sandboxalso carries an explicit (non-inherited) ACE for the bare machine-domain SID —S-1-5-21-<domain>with no user RID appended, whichicaclsrenders as an empty-namedMACHINE\principal:Since both the directory and the marker file exhibit the same malformed principal, the bug is likely in a shared "grant the current user" SID-construction helper used by the elevated setup binary, not in the marker-write path specifically. (Possibly relevant: on this machine the computer name is
ADMINand the username isadmin, in case the SID/name resolution is name-based somewhere.)**2. Manual
icaclsgrants get wiped by any entry point re-running setup.**The Desktop app, the VS Code extension, and the standalone CLI each validate the marker against their own configuration; whichever considers it incompatible re-runs the elevated setup helper, which rewrites the marker with the broken ACL again. In practice the VS Code extension reverted the manual fix that had been applied while repairing the Desktop app about an hour earlier, bringing back the
orchestrator_helper_incompleteloop. So the eventual fix indeed needs to apply the correct user ACE on every marker rewrite, as suggested above.3. Interim mitigation that survives rewrites (for anyone stuck on this until it's fixed):
A SYSTEM scheduled task re-grants the current user every 5 minutes, so any setup rerun is self-healed without further UAC prompts (worst case: click "Retry Windows setup" once more after ≤5 min). Remove with
schtasks /Delete /TN CodexMarkerAclFix /Fonce a fixed build ships.Minor correction to the environment listed above: the Windows app version is
26.707.3748.0(not 26.707.37448).I was facing this exact issue, every
codex sandbox/ desktop-app setup run completes the elevated helper successfully ("setup binary completed", users + firewall + WFP all OK), then codex immediately reportssandbox setup marker missing or incompatibleand fails with:When i tried accessing the
setup_marker.jsoni just couldn't which got me thinking that it was probably something weird with my windows setup. While diagnosing it I found that because my machine name was the exact same as my username, the permission was being granted to the machine's domain SID instead of my user's SID.Essentially: my machine name and my username are both
same_user_machine_name. When the setup helper grants the invoking user's marker ACE by account name,LookupAccountName("same_user_machine_name")resolves to the computer/domain object (SidTypeDomain) instead of the local user. Fun confirmation of the trap: runningicacls setup_marker.json /grant "same_user_machine_name:R"from an elevated shell also resolves to the domain SID and silently merges into the existing bogus ACE with "success", no change.Workaround that worked for me
Grant the read ACE by explicit SID, bypassing name resolution (elevated shell; get your SID from whoami /user):
Immediately after this,
codex sandbox -c 'windows.sandbox="elevated"' -- cmd /c whoamiruns inside the sandbox asCodexSandboxOffline, exit 0, no UAC. Another potential fix for my case was renaming the PC which i didn't tryHopefully this helps if anyone encounters a similar issue and it is in this weird setup state as i was.
Environment
I can confirm this exact issue on a newer Codex Desktop build.
Environment:
26.715.8383.0codex-cli 0.145.0-alpha.2710.0.26200.0x64tr-TRThe recurring error was:
The setup log indicated success:
I found some additional ACL evidence.
setup_marker.jsonexisted and was readable from an elevated PowerShell session, but the normal desktop user receivedAccess denied.The marker DACL did not contain an ACE for the actual desktop user.
icaclsdisplayed an unusual trustee similar to:The redacted SDDL indicated that this trustee used the machine/domain SID prefix without the desktop user's final RID:
The actual user SID would be:
Importantly, granting Full Control was not necessary. Granting only read permission on this single file was sufficient:
After this change:
<COMPUTER_NAME>\codexsandboxoffline.workspace-writeremained enabled.danger-full-accesswas not required.This suggests that the setup helper may be writing an incomplete account-domain SID as the marker-file trustee instead of the full desktop-user SID.
All usernames, computer names, and SID values above are redacted. No authentication or sandbox credential contents are included.
<img width="717" height="60" alt="Image" src="https://github.com/user-attachments/assets/1cac64ba-fea2-4550-bd60-8ac7d0796dc8" />
Sharing the Codex prompt that helped me diagnose and repair this
I am sharing this in case it helps someone experiencing the same problem.
I used Codex itself to investigate this issue on my machine. In my case, the elevated sandbox setup had completed and
setup_marker.jsonexisted, but the normal Windows user could not read the file because of its ACL. After granting that user read-only access to the single marker file, the setup loop stopped and theworkspace-writesandbox began working normally.This is only a community workaround based on what worked on my machine. It is not official OpenAI guidance, and the same “Windows setup did not finish” message can have other causes.
Environment in which I prepared and tested the prompt:
xhigh)26.715.8383.0codex-cli 0.145.0-alpha.2710.0.26200.0x64tr-TROther tool-capable Codex models may also be able to perform the diagnosis, but I only tested this workflow with the model and settings listed above.
If your symptoms match this issue, you can try pasting the prompt below into a Codex task. It asks Codex to diagnose the problem without making changes first and to wait for approval before applying the narrowly scoped repair.
If Codex cannot follow these safety constraints, or if it finds a different error, stop rather than allowing it to improvise broad permission changes.
---
Copyable Codex diagnostic and repair prompt
Copy everything inside the block between
BEGIN PROMPTandEND PROMPT, then paste it into a new Codex task.BEGIN PROMPT
END PROMPT
---
I hope this helps someone avoid the amount of troubleshooting this took on my machine. If the prompt finds a different root cause, please do not apply the marker ACL workaround blindly.
Confirmed on Codex Desktop
26.721.3996.0with Windows 11 build26200on a domain-joined computer.Symptoms:
codex-windows-sandbox-setup.exe - Application ErrorThe application was unable to start correctly (0xc0000142)%USERPROFILE%\.codex\.sandbox\setup_marker.jsonexisted.sandbox.logandsetup_error.jsonwere not present.icaclsfrom the normal account also returned access denied.I fixed it from an elevated PowerShell session by granting the actual domain user SID read-only access to the single marker file:
Afterward:
setup_marker.json.CodexSandboxOffline.The marker ACL contained permissions for SYSTEM, Administrators, and another local identity, but not the actual domain desktop account. Granting only
(R)onsetup_marker.jsonwas sufficient; no recursive ACL changes or Full Control were required.Usernames, domain names, computer names, and full SID values are redacted.
Thank you @pekideer
Claude helped me with this. Confirming this on a different install path, and I think I found the specific cause of the bad ACL.
Environment:
@openai/codexv0.146.0 installed viabun add -g, Windows 11 Home Single Language 10.0.26200, Microsoft-Account-linked local admin account. (Different from the reporter's Windows package 26.623.5546.0 / build 26100, so this isn't specific to one installer.)Why the ACL is wrong
The setup writes the user-facing ACE using the domain SID with the RID stripped off, instead of the account SID.
.sandboxdirectory SDDL (line breaks added, SIDs partly redacted):My actual account SID is
S-1-5-21-<A>-<B>-<C>-1001. The third ACE stops at the domain portion, so it matches no security principal at all.icaclsrenders it with an empty account name:and
NTAccount.Translate()throwsSome or all identity references could not be translated.setup_marker.jsongets the same treatment, with inheritance disabled. Its complete ACL, read as Administrator:Three ACEs, and the only intended user grant is dead. Under UAC a non-elevated process holds
BUILTIN\Administratorsas deny-only, socodex.exematches none of the three and gets a hard access-denied on a file it just wrote as admin. That's why the marker reads as "missing or incompatible" while being present and perfectly well-formed.So the fix is likely wherever that ACE's SID is constructed - it looks like the RID (last subauthority) is being dropped, leaving the domain SID.
Not stale state
I fully removed Codex first - package,
~\.codex, bothCodexSandbox*local accounts, theCodexSandboxUsersgroup, allcodex_sandbox_*firewall rules, and every sandbox ACE across my home directory - then reinstalled clean. The broken ACE was regenerated immediately using the current machine's domain SID.Self-test for anyone landing here
You're affected if an ACE's SID ends at the domain portion (
S-1-5-21-A-B-C) instead of a full account SID (S-1-5-21-A-B-C-<RID>), or if that command fails with access denied as your normal user.Notes on the workaround
The
icaclsgrant in the original post works. Two refinements:(R)is sufficient - no need for:F. The marker only needs to be readable by the non-elevated process.Also worth flagging: this comes back after any update that re-runs setup, since the same code path regenerates the broken ACE.
Why retrying is costly
Choosing "try setting up admin sandbox again" isn't free. Each attempt re-applies read ACEs across ~60 paths in the home directory plus write/deny ACEs on project trees, and because those are inheritable
(OI)(CI)ACEs, Windows re-stamps every descendant. On one 422k-file project directory here, a single ACL change took several minutes. My sandbox log shows three complete elevated setups in 47 seconds, each with its own UAC prompt.I can confirm this exact setup-marker ACL failure still occurs on a newer Codex Desktop/App-bundled CLI build.
Environment
26.727.6591.00.146.0-alpha.9.2Additional evidence
%USERPROFILE%\.codex\.sandbox\setup_marker.jsonACL contained an incomplete trustee rendered byicaclsas<MACHINE>\:(F).A narrowly scoped workaround was sufficient:
(R)to the actual desktop-user SID on the singlesetup_marker.jsonfile.danger-full-accesssetting was needed.Post-workaround validation:
whoami.exereturned<MACHINE>\codexsandboxoffline.apply_patchregression test passed its complete lifecycle: create, exact byte read-back, update, exact byte read-back, delete, and final absence verification underworkspace-write.This appears to be the same broader unqualified-user problem reported in #27376.
Public
mainatbb5054fstill:%USERNAME%asreal_user;LookupAccountNameW(NULL, name, ...)without requiringSidTypeUser; andFor a computer-name/username collision, the bare lookup can return the machine/domain SID rather than the user SID. A robust fix would be to capture and pass the initiating user's full SID before elevation—or use an unambiguous qualified identity—and reject a non-user SID result. A regression test should cover a local machine name equal to the username case-insensitively.
Status on my machine: locally mitigated. Upstream status: still unresolved.
Reproduced on Windows 10 Pro (build 19045), Codex Store package
26.818.3698.0, bundled CLI0.148.0-alpha.15. Adding a source-level root cause, because the marker DACL on this machine had a different shape than the bare-domain-SID cases reported above, yet the same end state: the unelevated user cannot open its ownsetup_marker.json.Observed state
%USERPROFILE%\.codex\.sandbox\setup_marker.jsonexisted (255 bytes, written by the elevated helper the previous day). From the interactive, unelevated session:Get-Content→Access is deniedicacls <marker>→ failed outright, i.e. the caller lacked evenREAD_CONTROLGet-Acl→UnauthorizedAccessExceptionsetup_error.jsonsandbox.logended withsetup binary completed,WFP setup succeeded ... 12 installed filters,setup refresh: processed 3 write roots (read roots delegated); errors=[]So the helper launched fine (this is not the os error 5 / 740 helper-launch bug) and every OS-level step succeeded. The parent directory
.sandboxdid carry an inherited ACE for the interactive user, but that is irrelevant: the marker's own DACL is created protected (D:P), so inheritance is blocked.After granting only the current user's SID on the marker,
icaclslisted exactly three ACEs: the freshly added user,NT AUTHORITY\SYSTEM, andBUILTIN\Administrators. No fourth trustee, and no empty-namedMACHINE\principal. Sinceicacls /grantmerges into an existing ACE for the same trustee and never removes ACEs, the pre-existing DACL had to beSYSTEM+Administratorsonly — meaning the "real user" ACE had collapsed into one of those two.The app had auto-updated that morning (new
%LOCALAPPDATA%\OpenAI\Codex\bin\<hash>\populated a few minutes before first use), which bumped the CLI and forced marker revalidation — that is why a marker written the day before only became fatal after the update.Root cause in current
main(2151d3a)The marker ACE is built from an account name, and that name comes from an environment variable with a fallback that silently grants the wrong principal.
codex-rs/windows-sandbox-rs/src/setup.rs— both payload construction sites:codex-rs/windows-sandbox-rs/src/bin/setup_main/win/sandbox_users.rs,prepare_setup_marker:Three independent defects feed the same failure:
1. The fallback grants
Administrators. IfUSERNAMEis absent from the payload-building process,real_userbecomes the literal"Administrators",resolve_sidmaps it throughwell_known_sid_strtoS-1-5-32-544, and the SDDL degenerates toD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;BA)— a protected DACL with no ACE for the interactive user at all. An unelevated token holdsAdministratorsas deny-only, so an admin user is locked out just as hard as a standard user. This exactly matches the DACL observed here. AUSERNAMEofSYSTEM(service/host context) collapses the same way into theSYACE.2.
resolve_sidignoresSID_NAME_USE. Both copies —winutil.rs::resolve_sidandsandbox_users.rs::resolve_sid— declarelet mut use_type: SID_NAME_USE = 0;, pass&mut use_typetoLookupAccountNameW, and never read it back. A name that resolves toSidTypeDomainis accepted as if it were a user, yielding a machine/domain SID with no RID. That is theMACHINE\:(F)/ machine-name-equals-username case reported earlier in this thread.3. Identity is name-derived, not token-derived.
USERNAMEis an inherited, mutable environment variable, not an identity. A DACL is the wrong place to trust it. The crate already has the correct primitive:codex-rs/windows-sandbox-rs/src/token.rs::get_user_sid_bytesdoesGetTokenInformation(TokenUser)→GetLengthSid→CopySid, which cannot be confused by name collisions, missing env vars, or locale.4. The failure is then reported as the wrong thing.
codex-rs/windows-sandbox-rs/src/identity.rs::load_markermaps every non-NotFoundI/O error toNone:PermissionDeniedis therefore indistinguishable from "no marker", which is why the UI says "sandbox setup marker missing or incompatible" and offers "Retry Windows setup". Retrying re-runs the helper, which rewrites the marker with the same broken DACL — the loop everyone in this thread is stuck in. The one signal that would identify the problem instantly is discarded one line earlier.Suggested approach
Sketch against
2151d3a, untested (no Rust toolchain on the affected machine — treat as direction, not a patch):#[serde(default)] real_user_sid: Option<String>toElevationPayload, populated on the caller side from the current process token via a safe wrapper over the existingget_user_sid_bytes+string_from_sid_bytes. Inprepare_setup_marker, prefer that SID.Administratorsfallback. If the caller's identity cannot be determined, returnSetupErrorCode::HelperSetupMarkerWriteFailedinstead of writing a marker nobody can read. Failing loudly is strictly better than a protected DACL that excludes the only principal that needs it.SID_NAME_USEwherever a name still has to be resolved: requireSidTypeUserfor the real user and rejectSidTypeDomain/SidTypeInvalid/SidTypeUnknownwith a distinct error. Both copies ofresolve_sidneed it; deduplicating them would also help.icaclsgrant survives only until the next entry point runs setup.PermissionDenieddistinctly inload_marker, and do not offer "Retry Windows setup" for it — retrying cannot fix an ACL the helper itself just wrote. An error naming the marker path and the denied access would have made this a one-minute diagnosis instead of a thread.Workaround confirmation
Granting by explicit SID (name resolution avoided, per the earlier comment in this thread) fixed it immediately, elevated:
Verification after the grant, unelevated, no UAC prompt:
Marker readable,
"version": 5, sandboxed process running as the offline sandbox user, exit 0.