Windows sandbox refresh fails with helper_sandbox_lock_failed after SetNamedSecurityInfoW(ERROR_ACCESS_DENIED) on existing .sandbox-bin
What version of Codex CLI is running?
codex-cli 0.146.0
What subscription do you have?
ChatGPT Pro
Which model were you using?
GPT-5.6 Sol Extended
What platform is your computer?
Windows build 26200 (x64)
What terminal emulator and version are you using (if applicable)?
PowerShell 7.6.4
Codex doctor report
What issue are you seeing?
Codex CLI 0.146.0 successfully completed initial Windows sandbox provisioning and launched the copied command runner.
Subsequent launches consistently fail before workspace initialization with:
helper_sandbox_lock_failed
lock sandbox bin dir D:\OpenAI\Codex\home\.sandbox-bin failed:
SetNamedSecurityInfoW sandbox dir failed: 5
The failure occurs before any repository is opened.
The issue is independent of the selected project because the failure occurs inside the Codex runtime while refreshing the existing .sandbox-bin directory.
During a read-only investigation I confirmed:
- Initial sandbox provisioning succeeds.
- Later sandbox refreshes consistently fail on the same directory.
- D: is a healthy NTFS volume.
- No reparse points were involved.
- Sandbox users and groups are valid.
- Runner binaries are correctly signed.
- Packaged and staged runner hashes match.
Static analysis of the signed helper indicates that the lock routine constructs a replacement DACL and invokes SetNamedSecurityInfoW with DACL_SECURITY_INFORMATION without first determining whether the existing descriptor already satisfies the required policy.
Observed behavior is consistent with an idempotence defect combined with an ownership lifecycle mismatch, although this remains a hypothesis pending engineering verification.
What steps can reproduce the bug?
- Install Codex CLI 0.146.0.
- Configure Windows sandbox normally.
- Complete initial sandbox provisioning.
- Verify the copied command runner launches successfully.
- Close Codex.
- Launch Codex again using workspace-write sandbox mode.
- Observe:
helper_sandbox_lock_failed
SetNamedSecurityInfoW sandbox dir failed: 5
- Repeat from different repositories.
The failure remains tied to D:\OpenAI\Codex\home\.sandbox-bin and occurs before repository initialization.
What is the expected behavior?
If the trusted runner directory already satisfies the required security policy, sandbox refresh should recognize the existing state and continue without attempting an unnecessary DACL rewrite.
Codex should continue through sandbox initialization and open the selected repository normally.
Additional information
A complete read-only investigation was performed.
No Windows permissions, ownership, ACLs, Codex files, repositories, or project files were modified after the failure was identified.
Evidence collected includes:
- sandbox logs
- environment validation
- ACL inspection
- ownership inspection
- SHA-256 verification
- signature verification
- timeline reconstruction
- evidence matrix
- root cause summary
- regression test proposal
Observed facts and hypotheses are clearly separated throughout the investigation.
If useful, I can provide the complete investigation package, including:
- LIVE_READ_ONLY_EVIDENCE.md
- ROOT_CAUSE_SUMMARY.md
- EVIDENCE_MATRIX.md
- TECHNICAL_TIMELINE.md
- HELPER_REVERSE_ENGINEERING.md
- REGRESSION_TEST_PLAN.md
- additional engineering artifacts
4 Comments
Additional investigation completed since opening this issue.
I performed a read-only investigation without modifying Windows permissions, ownership, ACLs, Codex files, repositories, or project state.
Key observations:
.sandbox-bindirectory.helper_sandbox_lock_failed
SetNamedSecurityInfoW sandbox dir failed: 5
The investigation includes:
Current engineering hypothesis (clearly identified as a hypothesis):
The refresh path appears to unconditionally attempt a DACL update on
.sandbox-binduring later launches instead of recognizing an already-valid security descriptor. This behavior is consistent with an idempotence issue combined with an ownership lifecycle mismatch, although confirmation would require maintainer-side symbols or a captured failing helper token.If useful, I can provide the complete investigation package or run additional controlled diagnostics requested by the Codex engineering team.
Same failure with an empty, freshly-created
.sandbox-bin— ownership is not the causeWe hit this on a centrally-managed deployment (Windows 11 25H2, x64) and ran a controlled experiment that I think rules out the idempotency/ownership theory.
Setup:
codex sandbox setup --elevated --user <DOMAIN>\<user> --codex-home C:\Users\<user>\.codex, launched by our management agent asNT AUTHORITY\SYSTEM.Versions: fails on
OpenAI.Codex 26.818.8289.0(codex-cli 0.149.0-alpha.4.3) and on26.818.5229.0/26.818.5345.0(0.149.0-alpha.4.1). Works on26.814.5167.0(codex-cli 0.148.0-alpha.15), same script, same machines, same SYSTEM context.We scripted three attempts, re-running the setup after each:
helper_sandbox_lock_failed: lock sandbox bin dir ...\.sandbox-bin failed: SetSecurityInfo sandbox dir failed: 5icacls <dir> /setowner <DOMAIN>\<user> /T /C /Q→ owner was already the target user (notCodexSandboxOffline/Online), so this was a no-op. Same failure..sandbox-binout of the way, confirmed gone, so the helper creates it from scratch → same failure.So the helper cannot apply the DACL to a directory it just created itself. That seems to rule out stale ownership from a previous provisioning run.
The pre-existing directory (from a successful run in July) was empty and carried these explicit ACEs, which may or may not be relevant:
Note SYSTEM gets Modify, not Full Control, on the explicit ACEs — and
SetSecurityInfoneedsWRITE_DAC. But that alone doesn't explain case 3.Side effect worth flagging: when it fails, the run still creates the
CodexSandboxOffline/CodexSandboxOnlinelocal accounts, hides them underSpecialAccounts\UserList, and adds the threecodex_sandbox_*firewall rules. It also leavessetup_marker.jsonas a 0-byte file. A provisioning script that checks "marker exists" will report success on a machine that has no working sandbox — and our EDR flags the hidden-account registry write, so the endpoint gets the security alert without getting the sandbox.Happy to provide more detail if useful.
Additional reproduction evidence: this is still reproducible with Codex CLI 0.149.1.
Environment:
CODEX_HOME=D:\Governance\08-Runtime\Agent-Runtime-State\Codexcodex doctorreports:helper_sandbox_lock_failedI also ran the documented command from a real elevated Administrator PowerShell:
It still returns Win32 error 5 (Access Denied) while processing the trusted runner directory at the
SetSecurityInfo/SetNamedSecurityInfoWstage.Additional observations:
CodexSandboxUsersgroup exists, but provisioning did not complete the ACL setup for the new CODEX_HOME.icaclsACL operations on the same directory succeed.cap_sidwas copied.This is a 0.149.1 reproduction supplement to #36475. It is intended to report the observed behavior only; I am not asserting an unverified implementation-level root cause. No tokens, API keys, auth files, MCP OAuth material, or configuration contents are included.
Independent reproduction: failure also occurs with
.sandbox-binabsent before elevated setupI can independently reproduce this failure on another Windows machine.
Environment:
windows-x86_64)CODEX_HOMEunderC:\Users\<user>\.codexThe relevant failure is:
I also tested with the previous
.sandbox-binmoved completely out of the way.Test sequence:
.sandbox-binACL/ownership..sandbox-binto a backup name..sandbox-binitself no longer existed.codex doctor --allthen reported:For this reproduction I did not manually change the ACL or ownership of
.sandbox-bin; the only state change was moving the previous directory aside before rerunning elevated setup.I also performed a separate Microsoft Defender investigation. No Codex-related Defender detection, quarantine/remediation, ASR action, or Controlled Folder Access action was recorded around the failures. Controlled Folder Access was disabled, and no effective ASR rules were identified that would explain the failure.
This seems especially relevant because the failure does not require the previous
.sandbox-bindirectory to still be present when elevated setup is started.This independently supports the observation in the other reproduction above that stale
.sandbox-binownership alone does not appear sufficient to explain the failure.I am not making an implementation-level root-cause claim here; this is intended as additional reproduction evidence. I can provide the corresponding ACL output and sandbox log excerpts if useful.