Windows Codex app: elevated sandbox cannot recover orphaned SYSTEM-DPAPI credentials (CryptUnprotectData 0x8009000B)
Open 💬 5 comments Opened Jul 28, 2026 by ColeRunsDiagnostics
What version of the Codex App are you using (From “About Codex” dialog)?
ChatGPT Windows app: 26.721.41059
What subscription do you have?
Plus
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64 OS revision 26100.8875
What issue are you seeing?
Every Codex task fails before any command process initializes:
execution error: Io(Custom {
kind: Other,
error: "windows sandbox: CryptUnprotectData failed: 2148073483"
})
Decimal 2148073483 equals 0x8009000B.
No shell, Git, or filesystem command executes. Even Get-Location,
Get-Date, whoami, and git --version remain unexecuted.
### What steps can reproduce the bug?
Minimal reproduction
1. Open the Codex Windows app using native Windows sandbox mode.
2. Use a disposable Git repository:
C:\Temp\CodexTest
3. Ask Codex to run Get-Location or git --version.
4. Sandbox initialization fails before process creation with the error above.
The failure reproduces:
• after multiple Windows restarts;
• after app reset and reinstall;
• when launching the app as Administrator;
• in a disposable repository;
• under a separate newly created local administrator account;
• after the unrelated platform outage was resolved;
• across recent app builds.
<img width="952" height="740" alt="Image" src="https://github.com/user-attachments/assets/d2ca938e-53ec-4bbb-9a1c-d7e11b0a29c5" />
<img width="607" height="572" alt="Image" src="https://github.com/user-attachments/assets/ec2bcbae-b13d-45c4-b6c9-308ae8d09ad3" />
### What is the expected behavior?
Expected behavior
When Codex-specific DPAPI-protected sandbox credentials cannot be decrypted
because their original SYSTEM master key is unavailable, setup should safely
regenerate the Codex-created users and their credential state.
Actual behavior
Sandbox initialization aborts permanently, and app reset, reinstall, elevated
launch, restarts, and a separate Windows account do not recover it.
### Additional information
Correlated Windows DPAPI evidence
Immediately after reproducing the failure, the enabled
Microsoft-Windows-Crypto-DPAPI/Operational log records:
Event 8198
DPAPI Unprotect failed
Status: 0x8009000B
ReasonForFailure: Could not get the master key
Related events at the identical timestamp and ActivityID show:
Security UserID: S-1-5-18
ProcessID: 1224
Process: lsass.exe
MasterKeyGUID: {REDACTED}
A read-only search of:
C:\Windows\System32\Microsoft\Protect\S-1-5-18
shows that the referenced master-key GUID is absent.
The SYSTEM DPAPI store itself is populated with multiple non-zero master-key
files and valid Preferred records, so this does not appear to be a generally
empty or destroyed SYSTEM DPAPI store.
Sandbox-account state
Both documented sandbox users exist and are enabled:
CodexSandboxOffline
PasswordLastSet: 7/25/2026 1:33:47 AM
LastLogon: 7/25/2026 1:38:40 AM
CodexSandboxOnline
PasswordLastSet: 7/25/2026 1:33:47 AM
LastLogon: none
This indicates setup provisioned both accounts and successfully logged on with
the Offline account once.
Documented log behavior
The documented log:
%USERPROFILE%\.codex\.sandbox\sandbox.log
has not updated since May 15, 2026. Current initialization failures occur before
that log records anything.
Architectural connection
OpenAI’s “Building the Codex Windows Sandbox” article explains that the elevated
sandbox creates CodexSandboxOffline and CodexSandboxOnline, stores their
credentials encrypted with DPAPI, and later decrypts those credentials before
launching codex-command-runner.exe through CreateProcessWithLogonW.
The observed failure appears to occur at that exact boundary:
stored sandbox-user credential
→ SYSTEM CryptUnprotectData
→ referenced master key unavailable
→ command runner never launches
→ sandbox initialization aborts
<img width="713" height="315" alt="Image" src="https://github.com/user-attachments/assets/0c378379-99db-4828-8ce3-696e3477cd24" />
<img width="377" height="217" alt="Image" src="https://github.com/user-attachments/assets/8348d389-266b-4e91-a579-cb1790a38543" />
5 Comments
they are going to their methyos soyboy moment of their own with this snadboxing shit
Update (Aug. 5, 2026)
<html>
<body>
<!--StartFragment--><html><head></head><body><h2><span>Investigation update — two distinct sandbox state failures identified and locally resolved</span></h2><p><span>I have now restored full Windows sandbox operation and can separate this incident into two distinct, sequential failures:</span></p><ol start="1"><li><p><span>An existing </span><code><span>sandbox_users.json</span></code><span> contained DPAPI-protected sandbox credentials that could no longer be decrypted.</span></p></li><li><p><span>After those credentials were deliberately regenerated, sandbox setup progressed further but failed because </span><code><span>setup_marker.json</span></code><span> was unreadable by the normal invoking Windows user.</span></p></li></ol><p><span>These were sequential blockers. The marker failure was hidden until the credential-store failure was removed.</span></p><h3><span>Executive assessment</span></h3><p><span>The original </span><code><span>CryptUnprotectData failed: 2148073483</span></code><span> condition did not disappear merely because an application update was installed.</span></p><p><span>It persisted until I deliberately moved the existing:</span></p><pre><code><span>%USERPROFILE%\.codex\.sandbox-secrets\sandbox_users.json</span></code></pre><p><span>aside and allowed Codex to create a new credential store.</span></p><p><span>Immediately after that regeneration:</span></p><ul><li><p><span>both offline and online sandbox credential entries existed;</span></p></li><li><p><span>each password field decoded to a 246-byte DPAPI-protected blob;</span></p></li><li><p><span>both blobs decrypted successfully under the current Windows user;</span></p></li><li><p><span>each produced a 24-byte plaintext password;</span></p></li><li><p><span>the next sandbox attempt no longer failed at </span><code><span>CryptUnprotectData</span></code><span>;</span></p></li><li><p><span>execution advanced to a later </span><code><span>orchestrator_helper_incomplete</span></code><span> / setup-marker failure.</span></p></li></ul><p><span>The second failure was then isolated to:</span></p><pre><code><span>%USERPROFILE%\.codex\.sandbox\setup_marker.json</span></code></pre><p><span>The current setup helper created this marker and reported successful completion, but the normal Codex process could not read the resulting file. Restoring access for the invoking Windows account made the marker immediately readable and restored sandbox operation.</span></p><p><span>The final recovery was verified through sandbox initialization, a disposable filesystem lifecycle, an application restart, and a real repository write lifecycle with no residual changes.</span></p><div><hr></div><h2><span>Phase 1: isolating the DPAPI credential failure</span></h2><p><span>The original failure occurred before any command process initialized:</span></p><pre><code><span>windows sandbox: CryptUnprotectData failed: 2148073483</span></code></pre><p><span>Decimal </span><code><span>2148073483</span></code><span> is </span><code><span>0x8009000B</span></code><span>, </span><code><span>NTE_BAD_KEY_STATE</span></code><span>.</span></p><p><span>The original issue also documented correlated Windows DPAPI telemetry:</span></p><pre><code><span>Event 8198
DPAPI Unprotect failed
Status: 0x8009000B
ReasonForFailure: Could not get the master key
Security UserID: S-1-5-18
Process: lsass.exe</span></code></pre><p><span>The referenced master-key GUID was absent from:</span></p><pre><code><span>C:\Windows\System32\Microsoft\Protect\S-1-5-18</span></code></pre><p><span>The broader SYSTEM DPAPI store was populated, so the evidence did not indicate a completely empty or destroyed DPAPI store. It instead suggested that the specific protected data referenced a key that was no longer available.</span></p><h3><span>Credential-scope comparison</span></h3><p><span>The two Codex credential systems were tested separately:</span></p><pre><code><span>%USERPROFILE%\.codex\auth.json
%USERPROFILE%\.codex\.sandbox-secrets\sandbox_users.json</span></code></pre><p><code><span>auth.json</span></code><span> was readable and was not the failing credential system.</span></p><p><span>The existing </span><code><span>sandbox_users.json</span></code><span> contained entries for:</span></p><pre><code><span>CodexSandboxOffline
CodexSandboxOnline</span></code></pre><p><span>Both stored password blobs failed DPAPI decryption with “Key not valid for use in specified state.”</span></p><p><span>As a control, an unrelated Chromium DPAPI-protected key belonging to the Codex application profile decrypted successfully under the same Windows account. That was important evidence: DPAPI was not generally nonfunctional for this Windows profile. The failure was isolated to the stored sandbox-password blobs.</span></p><h3><span>Working theory and targeted intervention</span></h3><p><span>The working theory was that the existing sandbox-password blobs had become stale, orphaned, corrupted, or incompatible with the security context in which Codex now attempted to decrypt them.</span></p><p><span>Possible upstream explanations remain:</span></p><ul><li><p><span>the credentials were protected under a different Windows security context;</span></p></li><li><p><span>a prior Codex build wrote them using a different DPAPI context or lifecycle;</span></p></li><li><p><span>a migration retained blobs after the corresponding DPAPI master key became unavailable;</span></p></li><li><p><span>reinstall/update behavior preserved credentials that should have been invalidated;</span></p></li><li><p><span>the application lacked an automatic recovery path when </span><code><span>CryptUnprotectData</span></code><span> returned </span><code><span>NTE_BAD_KEY_STATE</span></code><span>.</span></p></li></ul><p><span>Rather than modify DPAPI master keys, local-account password data, the SAM, or </span><code><span>auth.json</span></code><span>, I performed a narrow and reversible test:</span></p><ol start="1"><li><p><span>Fully stopped ChatGPT/Codex.</span></p></li><li><p><span>Moved—not deleted—the existing </span><code><span>sandbox_users.json</span></code><span> to a timestamped backup.</span></p></li><li><p><span>Restarted the application.</span></p></li><li><p><span>Reran elevated Windows sandbox setup.</span></p></li><li><p><span>Verified that Codex created a new </span><code><span>sandbox_users.json</span></code><span>.</span></p></li><li><p><span>Independently tested the new blobs without displaying their protected or plaintext values.</span></p></li></ol><p><span>The replacement file was created on August 5, 2026 at approximately 12:07 PM:</span></p><pre><code><span>Length: 828 bytes
CreationTime: 8/5/2026 12:07:01 PM
LastWriteTime: 8/5/2026 12:07:01 PM</span></code></pre><p><span>Both new credential entries passed DPAPI decryption:</span></p><pre><code><span>Mode: offline
ProtectedBytes: 246
Result: Decryptable
PlaintextLength: 24
Mode: online
ProtectedBytes: 246
Result: Decryptable
PlaintextLength: 24</span></code></pre><p><span>The very next smoke test advanced past DPAPI and failed later with:</span></p><pre><code><span>windows sandbox: orchestrator_helper_incomplete:
setup helper exited successfully before setup completed</span></code></pre><p><span>It also began reporting:</span></p><pre><code><span>sandbox setup required:
sandbox setup marker missing or incompatible</span></code></pre><p><span>This establishes the observed causal transition:</span></p><pre><code><span>Old sandbox_users.json present
↓
Both protected sandbox-password blobs fail DPAPI decryption
↓
Every sandbox attempt stops at CryptUnprotectData
↓
Old credential file moved aside
↓
Codex generates new offline and online credentials
↓
Both new blobs decrypt successfully
↓
CryptUnprotectData error disappears
↓
Sandbox reaches the subsequent setup-marker failure</span></code></pre><h3><span>Release-timeline qualification for the DPAPI finding</span></h3><p><span>The update history matters:</span></p><ul><li><p><span>The failure was present on the original reported 26.721 application line. The About dialog reported </span><code><span>26.721.41059</span></code><span>; the installed MSIX package observed during diagnostics was </span><code><span>26.721.4979.0</span></code><span>.</span></p></li><li><p><span>The Microsoft Store subsequently delivered </span><code><span>26.727.6591.0</span></code><span>.</span></p></li><li><p><span>The old </span><code><span>sandbox_users.json</span></code><span> still contained two undecryptable blobs after that update. Therefore, </span><code><span>26.727.6591.0</span></code><span> did not automatically recover the existing broken credential state.</span></p></li><li><p><span>The credential store was deliberately moved and regenerated while investigating that state.</span></p></li><li><p><code><span>26.730.8199.0</span></code><span> was installed later, after the broken credential file had already been replaced.</span></p></li></ul><p><span>Accordingly:</span></p><ul><li><p><span>The evidence supports that deliberate credential regeneration resolved the local DPAPI failure.</span></p></li><li><p><span>The evidence does not support attributing that recovery to </span><code><span>26.727</span></code><span>.</span></p></li><li><p><span>Because </span><code><span>26.730</span></code><span> was installed after regeneration, this machine cannot determine whether </span><code><span>26.730</span></code><span> contains code capable of recovering the old blobs; the old broken store was no longer active when that build ran.</span></p></li><li><p><span>It remains possible that Codex changed credential-generation or migration behavior during this release window. If so, the release still did not provide automatic recovery from an already-present undecryptable </span><code><span>sandbox_users.json</span></code><span> in the state actually observed.</span></p></li></ul><p><span>This is the product behavior I believe engineering should investigate: </span><code><span>NTE_BAD_KEY_STATE</span></code><span> on Codex-owned sandbox credentials currently appears capable of creating a permanent startup failure instead of triggering a safe, narrowly scoped credential regeneration path.</span></p><div><hr></div><h2><span>Phase 2: setup completed, but its marker was unreadable</span></h2><p><span>Once the credential store was regenerated, Codex consistently progressed into elevated sandbox setup.</span></p><p><span>The current helper successfully performed or reported:</span></p><ul><li><p><span>sandbox-user provisioning;</span></p></li><li><p><span>WFP configuration;</span></p></li><li><p><span>installation of 12 WFP filters;</span></p></li><li><p><span>write-root ACL processing;</span></p></li><li><p><span>read-ACL processing;</span></p></li><li><p><span>creation of a version-5 </span><code><span>setup_marker.json</span></code><span>;</span></p></li><li><p><code><span>setup binary completed</span></code><span>;</span></p></li><li><p><span>successful helper exit.</span></p></li></ul><p><span>However, the normal command runner never launched. The next command again reported:</span></p><pre><code><span>sandbox setup marker missing or incompatible</span></code></pre><p><span>followed by:</span></p><pre><code><span>orchestrator_helper_incomplete:
setup helper exited successfully before setup completed</span></code></pre><h3><span>Build-integrity verification</span></h3><p><span>At this stage, the installed and active package was:</span></p><pre><code><span>OpenAI.Codex_26.730.8199.0_x64__2p2nqsd0c76g0
Status: Ok</span></code></pre><p><span>Every active ChatGPT/Codex process used the </span><code><span>26.730.8199.0</span></code><span> package path.</span></p><p><span>The current cached executables matched their package copies by size and SHA-256:</span></p>
Binary | Size | SHA-256
-- | -- | --
codex.exe | 363,706,672 | FA960EC081BEC3629F40C63ED610EBC49C7E5E077DFB42322B08CB6D460F0B8A
codex-code-mode-host.exe | 56,721,712 | 910159E6F9460103C846D7723A2EF82BED90DE45C582E0E004DC2CE7D10A3C3F
codex-command-runner.exe | 1,302,320 | D2C2E8332EC93CEB048E924A4C728932B3D5AF247B98FE7C9C2DDFC2ADFA33F7
codex-windows-sandbox-setup.exe | 8,808,240 | 43B2658B5AB5D0A886E78CEE0510E605361EB33FBAC7D1F1DC7A195E58E6A944
<p><span>The older runtime-cache directory contained only </span><code><span>rg.exe</span></code><span>, not an older </span><code><span>codex.exe</span></code><span>, command runner, code-mode host, or setup helper.</span></p><p><span>This evidence rules out a mixed package/current-cache explanation for the behavior observed under </span><code><span>26.730.8199.0</span></code><span>.</span></p><h3><span>File-specific ACL evidence</span></h3><p><span>During a controlled setup attempt at approximately 12:49 PM, the log sequence was:</span></p><pre><code><span>12:49:08.382 codex.exe:
sandbox setup required: sandbox setup marker missing or incompatible
12:49:11.140:
ensuring sandbox users offline=CodexSandboxOffline online=CodexSandboxOnline
12:49:12.007:
WFP setup succeeded for CodexSandboxOffline with 12 installed filters
12:49:12.269:
read-acl-only mode: applying read ACLs
12:49:12.271 codex-windows-sandbox-setup.exe:
setup binary completed
12:49:12.279:
read ACL run completed</span></code></pre><p><span>The helper freshly recreated:</span></p><pre><code><span>%USERPROFILE%\.codex\.sandbox\setup_marker.json</span></code></pre><p><span>Immediately afterward:</span></p><ul><li><p><span>the file existed;</span></p></li><li><p><span>its timestamp showed that it had just been rewritten;</span></p></li><li><p><code><span>Get-Content</span></code><span> failed with Access Denied;</span></p></li><li><p><code><span>Get-Acl</span></code><span> failed with </span><code><span>UnauthorizedAccessException</span></code><span>;</span></p></li><li><p><code><span>icacls</span></code><span> reported Access Denied and processed zero files;</span></p></li><li><p><span>the normal Codex process classified the marker as “missing or incompatible”;</span></p></li><li><p><span>no </span><code><span>codex-command-runner.exe</span></code><span> launch followed.</span></p></li></ul><p><span>The parent </span><code><span>.sandbox</span></code><span> directory remained owned by the signed-in user and granted that user Full Control. The access failure was therefore specific to the newly created marker, rather than the parent directory.</span></p><p><span>Because Windows denied even ACL inspection from the normal account, I could not capture a complete pre-repair SDDL for the defective file. I therefore cannot state exactly which ACE was missing or protected. What is established is that the fresh file was unreadable, while its parent was accessible.</span></p><h3><span>Targeted ACL repair</span></h3><p><span>A narrowly scoped elevated repair was applied only to </span><code><span>setup_marker.json</span></code><span>.</span></p><p><span>Before mutation, the procedure:</span></p><ul><li><p><span>created a timestamped backup using backup mode;</span></p></li><li><p><span>preserved the file’s content, ownership, and ACL metadata;</span></p></li><li><p><span>separately saved the original ACL with </span><code><span>icacls /save</span></code><span>;</span></p></li><li><p><span>refused to continue if the backup failed.</span></p></li></ul><p><span>The repair then granted the invoking account Full Control without changing ownership.</span></p><p><span>Observed result:</span></p><pre><code><span>ROBOCOPY_EXIT=1
ICACLS_SAVE_EXIT=0
INITIAL_GRANT_EXIT=0
OWNER_CHANGED=False
MARKER_READABLE=True
MARKER_VERSION=5
MARKER_LENGTH=255</span></code></pre><p><span>The repaired ACL contained explicit Full Control for the invoking Windows user. Ownership remained:</span></p><pre><code><span>BUILTIN\Administrators</span></code></pre><p><span>Immediately after this one-file ACL repair:</span></p><ul><li><p><span>Codex accepted the existing marker;</span></p></li><li><p><span>sandbox initialization succeeded;</span></p></li><li><p><span>the setup loop stopped;</span></p></li><li><p><code><span>codex-command-runner.exe</span></code><span> launched;</span></p></li><li><p><span>no further DPAPI error occurred.</span></p></li></ul><p><span>This establishes the second causal transition:</span></p><pre><code><span>26.730 helper creates/rewrites version-5 marker
↓
Marker exists but normal invoking user cannot read it
↓
Codex reports marker “missing or incompatible”
↓
Setup repeats and orchestrator_helper_incomplete is returned
↓
Explicit access restored on that marker only
↓
Marker becomes readable and remains valid JSON
↓
Codex accepts marker
↓
Command runner launches and sandbox operations succeed</span></code></pre><div><hr></div><h2><span>Cross-version and multi-user evidence for the marker ACL issue</span></h2><p><span>The marker behavior is not unique to this machine or newly attributable to </span><code><span>26.730</span></code><span>.</span></p><p><span>Related public reports include:</span></p><ul><li><p><a href="https://github.com/openai/codex/issues/30445"><span>#30445 — Windows sandbox setup marker ACL prevents Codex from starting sandbox after UAC setup</span></a><span>, reported June 28, 2026 on package </span><code><span>26.623.5546.0</span></code><span>. The reporter found that granting the current user access to </span><code><span>setup_marker.json</span></code><span> immediately restored sandbox commands.</span></p></li><li><p><a href="https://github.com/openai/codex/issues/35407"><span>#35407 — Windows Desktop 26.721 repeats elevated sandbox setup; marker rewritten but unreadable/rejected</span></a><span>, reported July 25, 2026 on package </span><code><span>26.721.4979.0</span></code><span>. That report captured the same successful-helper/setup-loop behavior and an unreadable freshly rewritten marker.</span></p></li><li><p><a href="https://github.com/openai/codex/issues/23712"><span>#23712 — Windows Desktop repeatedly launches elevated setup helper</span></a><span>, reported May 20, 2026 on app version </span><code><span>26.513.40821</span></code><span>, records the earlier repeated “marker missing or incompatible” setup pattern, although it does not independently prove the marker ACL cause.</span></p></li></ul><p><span>My reproduction on </span><code><span>26.730.8199.0</span></code><span> extends the directly evidenced ACL problem across at least:</span></p><pre><code><span>26.623.5546.0
26.721.4979.0
26.730.8199.0</span></code></pre><p><span>Therefore:</span></p><ul><li><p><span>I do not believe </span><code><span>26.730</span></code><span> introduced the marker ACL defect.</span></p></li><li><p><code><span>26.730</span></code><span> did not repair it on this machine.</span></p></li><li><p><span>The evidence instead points to a longer-lived Windows sandbox marker-creation or ACL-inheritance issue that survived multiple releases.</span></p></li><li><p><span>The setup-loop symptom may extend further back, but only reports that directly tested marker readability should be treated as confirmation of the same root cause.</span></p></li></ul><p><span>The </span><code><span>26.727</span></code><span> build produced the setup-marker loop immediately after credential regeneration, but I did not capture the marker’s ACL in that build. The file-specific Access Denied condition was directly proven after the subsequent </span><code><span>26.730</span></code><span> update. It is therefore reasonable to say the same defect may have been present in </span><code><span>26.727</span></code><span>, but that specific build-level attribution is not proven by my data.</span></p><div><hr></div><h2><span>Post-repair validation</span></h2><h3><span>Disposable filesystem lifecycle</span></h3><p><span>A complete smoke test ran only within:</span></p><pre><code><span>C:\Temp\CodexTest</span></code></pre><p><span>Verified:</span></p><ul><li><p><span>sandbox initialization;</span></p></li><li><p><span>file creation;</span></p></li><li><p><span>exact-content write;</span></p></li><li><p><span>exact-content readback;</span></p></li><li><p><span>rename;</span></p></li><li><p><span>renamed-file verification;</span></p></li><li><p><span>deletion;</span></p></li><li><p><span>confirmation that no test artifacts remained;</span></p></li><li><p><span>no errors or warnings;</span></p></li><li><p><span>no access or modification outside the disposable directory.</span></p></li></ul><h3><span>Persistence across application restart</span></h3><p><span>After fully restarting the application:</span></p><ul><li><p><span>the “Try Windows setup again” condition did not return;</span></p></li><li><p><span>Codex accepted the existing setup state;</span></p></li><li><p><span>another sandbox task launched normally.</span></p></li></ul><h3><span>Repository lifecycle</span></h3><p><span>A controlled disposable-file test inside a real Git repository verified:</span></p><ul><li><p><span>initial </span><code><span>git status --short</span></code><span> recorded;</span></p></li><li><p><span>disposable file created;</span></p></li><li><p><span>exact content </span><code><span>FSBDL_WRITE_TEST_1</span></code><span> confirmed;</span></p></li><li><p><span>content changed to </span><code><span>FSBDL_WRITE_TEST_2</span></code><span> and confirmed;</span></p></li><li><p><span>file renamed;</span></p></li><li><p><span>file deleted;</span></p></li><li><p><span>both disposable paths absent afterward;</span></p></li><li><p><span>final </span><code><span>git status --short</span></code><span> exactly matched the initial state;</span></p></li><li><p><span>no existing repository file was modified;</span></p></li><li><p><span>no elevated filesystem fallback was used.</span></p></li></ul><p><span>This demonstrates more than UI recovery: the sandbox command runner resumed safe repository operations end to end.</span></p><div><hr></div><h2><span>Confirmed findings, strongest theories, and remaining unknowns</span></h2><h3><span>Confirmed</span></h3><ol start="1"><li><p><span>The old offline and online password blobs in </span><code><span>sandbox_users.json</span></code><span> were not decryptable.</span></p></li><li><p><span>An unrelated Codex-profile DPAPI key remained decryptable, so DPAPI was not generally broken for the signed-in Windows account.</span></p></li><li><p><span>Moving the old credential JSON caused Codex to generate a fresh credential store.</span></p></li><li><p><span>Both new password blobs decrypted successfully.</span></p></li><li><p><span>The </span><code><span>CryptUnprotectData</span></code><span> error disappeared immediately after regeneration.</span></p></li><li><p><span>The next blocker was a freshly created </span><code><span>setup_marker.json</span></code><span> that the invoking user could not read.</span></p></li><li><p><span>The </span><code><span>26.730</span></code><span> package, active processes, and runtime cache were internally consistent.</span></p></li><li><p><span>Granting the invoking user access to only the marker made Codex accept it.</span></p></li><li><p><span>Sandbox initialization and command execution then succeeded.</span></p></li><li><p><span>The repair persisted through application restart and a repository lifecycle test.</span></p></li></ol><h3><span>Strongest supported theory</span></h3><p><span>The incident consisted of two independently recoverable Codex-owned state failures:</span></p><ul><li><p><span>stale, orphaned, or context-incompatible DPAPI-protected sandbox credentials without an automatic recovery path;</span></p></li><li><p><span>a setup-marker ACL defect that prevented the normal process from reading state created by the elevated helper.</span></p></li></ul><h3><span>Not established</span></h3><ol start="1"><li><p><span>The exact Codex version or lifecycle event that originally made the old DPAPI blobs unusable.</span></p></li><li><p><span>Whether the missing SYSTEM master key resulted from a Codex update, failed credential migration, reinstall/reset behavior, Windows state change, or another event.</span></p></li><li><p><span>Whether </span><code><span>26.730</span></code><span> contains any DPAPI recovery change; the broken credential file had already been replaced before that build was installed.</span></p></li><li><p><span>The exact defective pre-repair marker SDDL, because the normal user could not read the file or its ACL.</span></p></li><li><p><span>Whether every user experiencing </span><code><span>CryptUnprotectData</span></code><span> has the same credential-file condition.</span></p></li><li><p><span>Whether every “marker missing or incompatible” report is an ACL defect; some may have other causes.</span></p></li></ol><div><hr></div><h2><span>Engineering recommendations</span></h2><h3><span>Credential-store recovery</span></h3><p><span>When decrypting a Codex-owned sandbox password returns </span><code><span>0x8009000B</span></code><span> or indicates that the required master key is unavailable, setup should not remain permanently blocked.</span></p><p><span>A safe recovery path could:</span></p><ol start="1"><li><p><span>distinguish sandbox credentials from ChatGPT account authentication;</span></p></li><li><p><span>preserve or quarantine the unreadable </span><code><span>sandbox_users.json</span></code><span> for diagnostics;</span></p></li><li><p><span>regenerate only the Codex-created sandbox-account passwords and protected blobs;</span></p></li><li><p><span>update the corresponding local sandbox-account passwords;</span></p></li><li><p><span>verify that both new blobs can be decrypted in the context that will later launch the command runner;</span></p></li><li><p><span>surface a precise diagnostic if regeneration fails.</span></p></li></ol><p><span>At minimum, the UI should explain that the sandbox credential store is unreadable and offer a scoped repair. App reset/reinstall did not clear this state in the originally reported condition.</span></p><h3><span>Marker creation and validation</span></h3><p><span>The elevated setup helper should ensure that the normal invoking user can read and validate </span><code><span>setup_marker.json</span></code><span> after setup completes.</span></p><p><span>Potential safeguards:</span></p><ol start="1"><li><p><span>explicitly preserve or grant the invoking user SID when creating/replacing the marker;</span></p></li><li><p><span>validate the final marker using the same unelevated identity/context as the desktop runtime;</span></p></li><li><p><span>avoid replacing an inheritable file with one carrying a protected ACL that excludes the caller;</span></p></li><li><p><span>distinguish “file absent,” “invalid schema/version,” and “Access Denied” instead of collapsing all three into “missing or incompatible”;</span></p></li><li><p><span>do not report helper success until the final marker is readable and accepted by the consuming process.</span></p></li></ol><p><span>Please consider linking this issue with #30445 and #35407. The matching repair result across multiple users and multiple package generations makes the marker ACL behavior appear product-level rather than machine-specific.</span></p><h3><span>Current status</span></h3><p><span>The sandbox is operational on this machine after:</span></p><ol start="1"><li><p><span>deliberately regenerating </span><code><span>sandbox_users.json</span></code><span>; and</span></p></li><li><p><span>restoring access to </span><code><span>setup_marker.json</span></code><span>.</span></p></li></ol><p><span>I am retaining the old credential-store backup, marker backup, saved ACL data, repair transcript, and relevant logs in case engineering wants specific artifacts or a controlled follow-up test.</span></p><p><span>I do not recommend closing the issue solely because the local installation has recovered. Both recovery steps addressed Codex-owned state that the application did not repair automatically, and the marker ACL defect has independent cross-version reports from other users.</span></p></body></html><!--EndFragment-->
</body>
</html>## Investigation update — two distinct sandbox state failures identified and locally resolved
I have now restored full Windows sandbox operation and can separate the investigation into two distinct failures:
sandbox_users.jsoncontained DPAPI-protected sandbox credentials that could no longer be decrypted.setup_marker.jsonwas unreadable by the normal invoking Windows user.These were sequential blockers. The marker failure was hidden until the credential-store failure was removed.
Executive assessment
The original
CryptUnprotectData failed: 2148073483condition did not disappear merely because an application update was installed.It persisted until I deliberately moved the existing:
aside and allowed Codex to create a new credential store.
Immediately after that regeneration:
CryptUnprotectData;orchestrator_helper_incomplete/ setup-marker failure.The second failure was then isolated to:
The current setup helper created this marker and reported successful completion, but the normal Codex process could not read the resulting file. Restoring access for the invoking Windows account made the marker immediately readable and restored sandbox operation.
The final recovery was verified through sandbox initialization, a disposable filesystem lifecycle, an application restart, and a real repository write lifecycle with no residual changes.
---
Phase 1: isolating the DPAPI credential failure
The original failure occurred before any command process initialized:
Decimal
2148073483is0x8009000B,NTE_BAD_KEY_STATE.The original issue also documented correlated Windows DPAPI telemetry:
The referenced master-key GUID was absent from:
The broader SYSTEM DPAPI store was populated, so the evidence did not indicate a completely empty or destroyed DPAPI store. It instead suggested that the specific protected data referenced a key that was no longer available.
Credential-scope comparison
The two Codex credential systems were tested separately:
auth.jsonwas readable and was not the failing credential system.The existing
sandbox_users.jsoncontained entries for:Both stored password blobs failed DPAPI decryption with “Key not valid for use in specified state.”
As a control, an unrelated Chromium DPAPI-protected key belonging to the Codex application profile decrypted successfully under the same Windows account. That was important evidence: DPAPI was not generally nonfunctional for this Windows profile. The failure was isolated to the stored sandbox-password blobs.
Working theory and targeted intervention
The working theory was that the existing sandbox-password blobs had become stale, orphaned, corrupted, or incompatible with the security context in which Codex now attempted to decrypt them.
Possible upstream explanations remain:
CryptUnprotectDatareturnedNTE_BAD_KEY_STATE.Rather than modify DPAPI master keys, local-account password data, the SAM, or
auth.json, I performed a narrow and reversible test:sandbox_users.jsonto a timestamped backup.sandbox_users.json.The replacement file was created on August 5, 2026 at approximately 12:07 PM:
Both new credential entries passed DPAPI decryption:
The very next smoke test advanced past DPAPI and failed later with:
It also began reporting:
This establishes the observed causal transition:
Release-timeline qualification for the DPAPI finding
The update history matters:
26.721.41059; the installed MSIX package observed during diagnostics was26.721.4979.0.26.727.6591.0.sandbox_users.jsonstill contained two undecryptable blobs after that update. Therefore,26.727.6591.0did not automatically recover the existing broken credential state.26.730.8199.0was installed later, after the broken credential file had already been replaced.Accordingly:
26.727.26.730was installed after regeneration, this machine cannot determine whether26.730contains code capable of recovering the old blobs; the old broken store was no longer active when that build ran.sandbox_users.jsonin the state actually observed.This is the product behavior I believe engineering should investigate:
NTE_BAD_KEY_STATEon Codex-owned sandbox credentials currently appears capable of creating a permanent startup failure instead of triggering a safe, narrowly scoped credential regeneration path.---
Phase 2: setup completed, but its marker was unreadable
Once the credential store was regenerated, Codex consistently progressed into elevated sandbox setup.
The current helper successfully performed or reported:
setup_marker.json;setup binary completed;However, the normal command runner never launched. The next command again reported:
followed by:
Build-integrity verification
At this stage, the installed and active package was:
Every active ChatGPT/Codex process used the
26.730.8199.0package path.The current cached executables matched their package copies by size and SHA-256:
| Binary | Size | SHA-256 |
|---|---:|---|
|
codex.exe| 363,706,672 |FA960EC081BEC3629F40C63ED610EBC49C7E5E077DFB42322B08CB6D460F0B8A||
codex-code-mode-host.exe| 56,721,712 |910159E6F9460103C846D7723A2EF82BED90DE45C582E0E004DC2CE7D10A3C3F||
codex-command-runner.exe| 1,302,320 |D2C2E8332EC93CEB048E924A4C728932B3D5AF247B98FE7C9C2DDFC2ADFA33F7||
codex-windows-sandbox-setup.exe| 8,808,240 |43B2658B5AB5D0A886E78CEE0510E605361EB33FBAC7D1F1DC7A195E58E6A944|The older runtime-cache directory contained only
rg.exe, not an oldercodex.exe, command runner, code-mode host, or setup helper.This evidence rules out a mixed package/current-cache explanation for the behavior observed under
26.730.8199.0.File-specific ACL evidence
During a controlled setup attempt at approximately 12:49 PM, the log sequence was:
The helper freshly recreated:
Immediately afterward:
Get-Contentfailed with Access Denied;Get-Aclfailed withUnauthorizedAccessException;icaclsreported Access Denied and processed zero files;codex-command-runner.exelaunch followed.The parent
.sandboxdirectory remained owned by the signed-in user and granted that user Full Control. The access failure was therefore specific to the newly created marker, rather than the parent directory.Because Windows denied even ACL inspection from the normal account, I could not capture a complete pre-repair SDDL for the defective file. I therefore cannot state exactly which ACE was missing or protected. What is established is that the fresh file was unreadable, while its parent was accessible.
Targeted ACL repair
A narrowly scoped elevated repair was applied only to
setup_marker.json.Before mutation, the procedure:
icacls /save;The repair then granted the invoking account Full Control without changing ownership.
Observed result:
The repaired ACL contained explicit Full Control for:
Ownership remained:
Immediately after this one-file ACL repair:
codex-command-runner.exelaunched;This establishes the second causal transition:
---
Cross-version and multi-user evidence for the marker ACL issue
The marker behavior is not unique to this machine or newly attributable to
26.730.Related public reports include:
26.623.5546.0. The reporter found that granting the current user access tosetup_marker.jsonimmediately restored sandbox commands.26.721.4979.0. That report captured the same successful-helper/setup-loop behavior and an unreadable freshly rewritten marker.26.513.40821, records the earlier repeated “marker missing or incompatible” setup pattern, although it does not independently prove the marker ACL cause.My reproduction on
26.730.8199.0extends the directly evidenced ACL problem across at least:Therefore:
26.730introduced the marker ACL defect.26.730did not repair it on this machine.The
26.727build produced the setup-marker loop immediately after credential regeneration, but I did not capture the marker’s ACL in that build. The file-specific Access Denied condition was directly proven after the subsequent26.730update. It is therefore reasonable to say the same defect may have been present in26.727, but that specific build-level attribution is not proven by my data.---
Post-repair validation
Disposable filesystem lifecycle
A complete smoke test ran only within:
Verified:
Persistence across application restart
After fully restarting the application:
Repository lifecycle
A controlled disposable-file test inside a real Git repository verified:
git status --shortrecorded;FSBDL_WRITE_TEST_1confirmed;FSBDL_WRITE_TEST_2and confirmed;git status --shortexactly matched the initial state;This was the first successful end-to-end repository operation since the original CryptUnprotectData failure began.
This demonstrates more than UI recovery: the sandbox command runner resumed safe repository operations end to end.
---
Confirmed findings, strongest theories, and remaining unknowns
Confirmed
sandbox_users.jsonwere not decryptable.CryptUnprotectDataerror disappeared immediately after regeneration.setup_marker.jsonthat the invoking user could not read.26.730package, active processes, and runtime cache were internally consistent.Strongest supported theory
The incident consisted of two independently recoverable Codex-owned state failures:
Not established
26.730contains any DPAPI recovery change; the broken credential file had already been replaced before that build was installed.CryptUnprotectDatahas the same credential-file condition.---
Engineering recommendations
Credential-store recovery
When decrypting a Codex-owned sandbox password returns
0x8009000Bor indicates that the required master key is unavailable, setup should not remain permanently blocked.A safe recovery path could:
sandbox_users.jsonfor diagnostics;At minimum, the UI should explain that the sandbox credential store is unreadable and offer a scoped repair. App reset/reinstall did not clear this state in the originally reported condition.
Marker creation and validation
The elevated setup helper should ensure that the normal invoking user can read and validate
setup_marker.jsonafter setup completes.Potential safeguards:
Please consider linking this issue with #30445 and #35407. The matching repair result across multiple users and multiple package generations makes the marker ACL behavior appear product-level rather than machine-specific.
Current status
The sandbox is operational on this machine after:
sandbox_users.json; andsetup_marker.json.I am retaining the old credential-store backup, marker backup, saved ACL data, repair transcript, and relevant logs in case engineering wants specific artifacts or a controlled follow-up test.
I do not recommend closing the issue solely because the local installation has recovered. Both recovery steps addressed Codex-owned state that the application did not repair automatically, and the marker ACL defect has independent cross-version reports from other users.
I can confirm this failure independently on Codex Desktop for Windows today.
Observed error on every local process launch:
Additional reproduction evidence from this session:
cmd /c echo tool-ok; failure occurs before process creation.apply_patch, shell execution, skill-file reads, and the Node REPL MCP all fail because they ultimately hit the same Windows sandbox credential initialization.This has a severe production impact: a long-running engineering task becomes completely unusable, and the only partial escape is requesting non-sandbox execution, which forces additional approval prompts. Recent Desktop updates have added more approval friction while this core Windows sandbox reliability problem remains unresolved. From a user perspective, frequent feature updates are not helpful when basic local execution can be permanently disabled and routine work requires repeated/batch approvals. The experience is extremely frustrating and not suitable for sustained professional development.
Requested fixes:
No source code, customer data, device identifiers, or project-specific paths are included in this report.
I am the reporter of duplicate issue #36052 and can confirm the same failure on another Windows environment.
The issue is still reproducible as of August 12, 2026:
windows sandbox: CryptUnprotectData failed: 2148073483apply_patchand the browser-control runtime can fail with the same error.Original duplicate report: #36052
And today