Standalone Windows CLI `:workspace` profile creates unsupported split roots and breaks `apply_patch`
What version of Codex CLI is running?
codex-cli 0.145.0
What subscription do you have?
ChatGPT Plus
Which model were you using?
GPT-5.6
What platform is your computer?
Windows 11 Pro, x64, build 26200.
Shell: PowerShell 7.
Summary
The standalone Codex CLI on native Windows selects the built-in :workspace permission profile, which includes both the active workspace and system temporary directories as writable roots. The unelevated restricted-token sandbox cannot enforce that split writable-root set, so apply_patch refuses to run before it reads or changes an existing workspace file.
This is not limited to Codex Desktop. Live process inspection showed that the session was hosted directly by the standalone lowercase CLI executable, with no packaged Codex.exe UI process running.
The safe refusal to run unsandboxed is correct. The defect is that a built-in CLI permission profile produces a policy shape that the selected supported Windows backend cannot enforce.
Actual behavior
Updating an existing workspace file with apply_patch fails before file access:
apply_patch verification failed: Failed to read file to update <workspace>\<file>:
failed to prepare fs sandbox:
failed to prepare windows sandbox wrapper:
windows unelevated restricted-token sandbox cannot enforce split writable root sets directly; refusing to run unsandboxed
The failure reproduced on three consecutive apply_patch attempts. No target file was changed.
Ordinary sandboxed PowerShell reads and commands continue to work.
Steps to reproduce
- Run the standalone Codex CLI on native Windows.
- Configure the fallback Windows sandbox:
``toml``
[windows]
sandbox = "unelevated"
- Use the built-in
:workspacepermission profile. In the reproduced session, the sandboxed command environment reported:
``text``
CODEX_PERMISSION_PROFILE=:workspace
CODEX_SANDBOX_NETWORK_DISABLED=1
- Open a writable Git workspace.
- Ask Codex to update an existing file using the internal
apply_patchtool. - Observe that the tool fails before reading the file with the split-root error above.
The effective writable-root set supplied to the session contained:
- the active workspace;
C:\tmp;- the
:tmpdirspecial root; and - the
:slash_tmpspecial root.
No user-configured additional writable directory was required.
Research and diagnostic steps performed
- Reproduced the exact
apply_patchfailure three consecutive times against existing workspace files. - Verified that normal sandboxed PowerShell commands and workspace reads work.
- Inspected the process ancestry using the non-mutating PowerShell process API:
``text``
pwsh.exe
parent -> C:\Users\<user>\AppData\Local\Programs\OpenAI\Codex\bin\codex.exe
- Enumerated running OpenAI/Codex processes. The primary runtime was lowercase standalone
codex.exe; no separate packagedCodex.exeDesktop/UI process was present. - Verified command resolution:
``text``
Get-Command codex
-> C:\Users\<user>\AppData\Local\Programs\OpenAI\Codex\bin\codex.exe
- Inspected relevant session markers and confirmed
CODEX_PERMISSION_PROFILE=:workspace. - Inspected the user configuration. The relevant configuration contained only:
``toml``
[windows]
sandbox = "unelevated"
It did not define sandbox_mode, default_permissions, [sandbox_workspace_write], or a custom [permissions.*] profile.
- Ran
codex doctor --json --all. Configuration and installation checks completed, but the doctor workflow did not perform an actualapply_patchcreate/update/delete health probe and therefore did not detect this failure. - Compared the observed policy with the current permissions documentation. The built-in
:workspaceprofile is documented to allow writes inside active workspace roots and system temporary directories. - Reviewed related reports #30712, #31220, and #32314. Those establish related split-root behavior, but #30712 and #31220 frame it primarily as Desktop-managed injection, while #32314 includes CLI exposure as one part of a larger elevated-sandbox performance report.
Root-cause analysis
The evidence supports this causal chain:
- The standalone CLI selects the built-in
:workspaceprofile. - By definition,
:workspacemakes both the active workspace and system temporary directories writable. - These are disjoint filesystem roots on native Windows.
- The unelevated restricted-token backend cannot safely enforce every split read/write policy.
- The
apply_patchfilesystem wrapper detects the unsupported policy and correctly refuses to fall back to unsandboxed execution. - Therefore, the standard built-in write profile and the supported unelevated Windows backend are mutually incompatible for this tool path.
This was ruled out as:
- a Codex Desktop background process;
- a repository-specific configuration problem;
- an NTFS permission problem on the target file;
- malformed patch syntax;
- a Git-state problem; or
- an authentication problem.
Expected behavior
A built-in permission profile offered by the standalone CLI should always resolve to a policy that the selected supported sandbox backend can enforce.
At least one of the following should occur:
- The unelevated Windows backend supports the split writable-root set used by
:workspace. - On unelevated Windows,
:workspaceconsolidates temporary writes under the active workspace—for example, through a workspace-local runtime temp directory—so the backend receives one writable root. - Codex omits system temporary directories from the effective writable set when the active tool operation does not require them.
- Session startup rejects the incompatible profile/backend combination with an actionable message before work begins, rather than advertising a writable workspace and failing only when
apply_patchis invoked.
apply_patch should be able to create, update, and delete files inside the active workspace without full access, shell-based file rewriting, or an approval that broadens authority.
Security and workflow impact
The current behavior disables the precise, auditable edit path and pressures agents toward shell-based rewrites, full access, or escalated execution. Refusing to run unsandboxed is the right security behavior; the durable fix is to prevent the default CLI profile from creating an unenforceable policy.
Suggested deterministic regression test
On native Windows with windows.sandbox="unelevated" and the built-in :workspace profile:
- Assert that the effective permission policy is accepted at session startup.
- Use internal
apply_patchto create, update, and delete a disposable file beneath the workspace. - Assert that each operation succeeds.
- Assert that writes outside the workspace and approved runtime-temp boundary fail.
- Assert that no unsandboxed fallback or escalation occurred.
Related issues
- #30712 — Desktop-managed split writable roots break
apply_patch. - #31220 — Desktop sandbox modes expose incompatible shell and patch behavior.
- #32314 — CLI and Desktop reproduction reported as part of elevated-sandbox performance analysis.
This report isolates the standalone CLI profile/backend incompatibility and includes process-level evidence that Desktop was not involved.
9 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Analysis (community)
Thank you for the careful report — the process ancestry, exact config, and writable-root enumeration make this very easy to reason about from source.
codex-cli 0.145.0, Windows 11 Pro x64 build 26200, PowerShell 7; config only[windows] sandbox = "unelevated"; session markersCODEX_PERMISSION_PROFILE=:workspaceandCODEX_SANDBOX_NETWORK_DISABLED=1; process tree under standalone…\OpenAI\Codex\bin\codex.exe(not Desktop UI).apply_patchfailures as the primary runtime evidence. What follows is source-level confirmation on currentmainthat the observed error string and failure path match a real policy/backend mismatch for the default CLI profile.apply_patchfails before reading the target withwindows unelevated restricted-token sandbox cannot enforce split writable root sets directly; refusing to run unsandboxedafter
failed to prepare fs sandbox/failed to prepare windows sandbox wrapper. Effective writable set includes workspace +C:\tmp+:tmpdir+:slash_tmp. Ordinary sandboxed shell still works.:workspace) should resolve to a policy the selected Windows backend can enforce, without weakening the correct refuse-unsandboxed behavior.Root-cause hypothesis
High confidence that this is a default profile shape vs unelevated overlay checker mismatch, not a bad patch or NTFS issue.
:workspacealways grants temp specials.PermissionProfile::workspace_write()(codex-rs/protocol/src/models.rs) callsworkspace_write_with(..., exclude_tmpdir_env_var=false, exclude_slash_tmp=false).FileSystemSandboxPolicy::workspace_write(codex-rs/protocol/src/permissions.rs) therefore adds Write on:slash_tmpand:tmpdir(plus project roots and the usual.git/.agents/.codexcarveouts).:slash_tmpresolves to/tmpwhenever that path is a directory.resolve_file_system_special_path(SlashTmp)buildsAbsolutePathBuf("/tmp")and includes it ifis_dir(). On Windows that commonly surfaces asC:\tmp, matching the issue’s writable-root list.apply_patchhits the unelevated restricted-token overlay path.FS helper prep ends in
resolve_windows_restricted_token_filesystem_overrides(codex-rs/sandboxing/src/windows.rs). WithWindowsSandboxLevel::RestrictedToken/ unelevated, that function compares:SandboxPolicyprojection, vsFileSystemSandboxPolicy::get_writable_roots_with_cwd.If the two
BTreeSets differ, it hard-errors with the exact string above and setswrite_roots_override: None(unelevated only layers extra deny-write carveouts).Legacy
SandboxPolicy::get_writable_roots_with_cwd(codex-rs/protocol/src/protocol.rs) only adds/tmpundercfg!(unix) && !exclude_slash_tmp.Split policy still resolves
:slash_tmpwhenever/tmpexists as a dir — platform-independent.So with
C:\tmppresent, split includes an extra root the legacy projection never had → equality check fails → refuse unsandboxed (correct security posture).ResolvedWindowsSandboxPermissions::writable_roots_for_cwd(codex-rs/windows-sandbox-rs/src/resolved_permissions.rs) stripsSlashTmp/Tmpdirspecials and re-adds temp viaTEMP/TMP. Elevated prep can emitwrite_roots_overridewhen sets diverge; unelevated does not. Existing unit coverage (windows_restricted_token_allows_workspace_write_profilesincodex-rs/core/src/exec_tests.rs) only asserts unelevated success when temps are excluded (exclude_tmpdir_env_var=true,exclude_slash_tmp=true) — i.e. not the built-in default.apply_patchverification/update does not.Related class (same error surface, different entry points): #30712, #31220, #32314, #33806, #34970. #34088 closed after switching to elevated — a workable user workaround, not a code fix for the default CLI + unelevated combination.
High-level fix outline (not a PR)
Prefer a small, policy + comparison alignment change over expanding unelevated capability first:
:slash_tmpas a Windows writable special for the built-in:workspaceprofile (or defaultexclude_slash_tmpon Windows / when the backend is unelevated restricted-token). Keep temp writability via the existingTEMP/TMPpath inresolved_permissions.resolve_windows_restricted_token_filesystem_overrides, compare writable roots using the same Windows-normalized root set the runtime already builds (stripSlashTmp/Tmpdir, remap temp) so protocol specials do not invent a second incompatible root set for the equality check alone.codex doctordiagnostic when unelevated + multi-root profile is still unenforceable for theapply_patch/ direct-FS path — today doctor does not probe create/update/delete under the selected backend.Alternatives considered (heavier or riskier):
write_roots_overridelike elevated (real capability/security review).apply_patchonly (inconsistent; hits elevated perf/setup issues from #32314 / #31220).Non-goals / do not weaken:
.git/.agents/.codexcarveouts.Happy to drop any of (1)–(3) if the team already has a preferred backend-side direction.
Test ideas
What should fail before / pass after if the team (or an invitee) implements:
PermissionProfile::workspace_write()with default temps included +WindowsSandboxLevel::RestrictedToken+ a layout whereAbsolutePathBuf("/tmp")exists as a directory →unsupported_windows_restricted_token_sandbox_reasonisNoneandresolve_windows_restricted_token_filesystem_overridesreturnsOk(_), not the split-root error.windows_restricted_token_allows_workspace_write_profilesto cover built-in defaults, not onlyexclude_* = true.:workspaceapply_patchcreate / update / delete of a disposable workspace file succeeds with no unsandboxed fallback; write outside workspace still denied.Questions for maintainers
:slash_tmp, align temp toTEMP/TMP), or in the unelevated backend (multi-rootwrite_roots_override)?C:\tmprequired to repro, or do other multi-root cases (extra--add-dir, plugins, Desktop viz roots as in #34970) hit the same equality check without it?codex doctorgrow anapply_patchcreate/update probe under the selected Windows backend?needs_direct_runtime_enforcementstays false, while only direct-FS tools fail?Please correct any of the above — especially if the team already treats Windows
:slash_tmpas intentional or has an in-flight elevated/unelevated redesign.Happy to refine this analysis with more pointers or a tighter repro matrix. If the team later wants an invited PR on an agreed approach, I’d be glad to help; no unsolicited PR from me.
Analysis (community)
Thank you for the careful report — the process ancestry, exact config, and writable-root enumeration make this very easy to reason about from source.
codex-cli 0.145.0, Windows 11 Pro x64 build 26200, PowerShell 7; config only[windows] sandbox = "unelevated"; session markersCODEX_PERMISSION_PROFILE=:workspaceandCODEX_SANDBOX_NETWORK_DISABLED=1; process tree under standalone…\OpenAI\Codex\bin\codex.exe(not Desktop UI).apply_patchfailures as the primary runtime evidence. What follows is source-level confirmation on currentmainthat the observed error string and failure path match a real policy/backend mismatch for the default CLI profile.apply_patchfails before reading the target withwindows unelevated restricted-token sandbox cannot enforce split writable root sets directly; refusing to run unsandboxedafter
failed to prepare fs sandbox/failed to prepare windows sandbox wrapper. Effective writable set includes workspace +C:\tmp+:tmpdir+:slash_tmp. Ordinary sandboxed shell still works.:workspace) should resolve to a policy the selected Windows backend can enforce, without weakening the correct refuse-unsandboxed behavior.Root-cause hypothesis
High confidence that this is a default profile shape vs unelevated overlay checker mismatch, not a bad patch or NTFS issue.
:workspacealways grants temp specials.PermissionProfile::workspace_write()(codex-rs/protocol/src/models.rs) callsworkspace_write_with(..., exclude_tmpdir_env_var=false, exclude_slash_tmp=false).FileSystemSandboxPolicy::workspace_write(codex-rs/protocol/src/permissions.rs) therefore adds Write on:slash_tmpand:tmpdir(plus project roots and the usual.git/.agents/.codexcarveouts).:slash_tmpresolves to/tmpwhenever that path is a directory.resolve_file_system_special_path(SlashTmp)buildsAbsolutePathBuf("/tmp")and includes it ifis_dir(). On Windows that commonly surfaces asC:\tmp, matching the issue’s writable-root list.apply_patchhits the unelevated restricted-token overlay path.FS helper prep ends in
resolve_windows_restricted_token_filesystem_overrides(codex-rs/sandboxing/src/windows.rs). WithWindowsSandboxLevel::RestrictedToken/ unelevated, that function compares:SandboxPolicyprojection, vsFileSystemSandboxPolicy::get_writable_roots_with_cwd.If the two
BTreeSets differ, it hard-errors with the exact string above and setswrite_roots_override: None(unelevated only layers extra deny-write carveouts).Legacy
SandboxPolicy::get_writable_roots_with_cwd(codex-rs/protocol/src/protocol.rs) only adds/tmpundercfg!(unix) && !exclude_slash_tmp.Split policy still resolves
:slash_tmpwhenever/tmpexists as a dir — platform-independent.So with
C:\tmppresent, split includes an extra root the legacy projection never had → equality check fails → refuse unsandboxed (correct security posture).ResolvedWindowsSandboxPermissions::writable_roots_for_cwd(codex-rs/windows-sandbox-rs/src/resolved_permissions.rs) stripsSlashTmp/Tmpdirspecials and re-adds temp viaTEMP/TMP. Elevated prep can emitwrite_roots_overridewhen sets diverge; unelevated does not. Existing unit coverage (windows_restricted_token_allows_workspace_write_profilesincodex-rs/core/src/exec_tests.rs) only asserts unelevated success when temps are excluded (exclude_tmpdir_env_var=true,exclude_slash_tmp=true) — i.e. not the built-in default.apply_patchverification/update does not.Related class (same error surface, different entry points): #30712, #31220, #32314, #33806, #34970. #34088 closed after switching to elevated — a workable user workaround, not a code fix for the default CLI + unelevated combination.
High-level fix outline (not a PR)
Prefer a small, policy + comparison alignment change over expanding unelevated capability first:
:slash_tmpas a Windows writable special for the built-in:workspaceprofile (or defaultexclude_slash_tmpon Windows / when the backend is unelevated restricted-token). Keep temp writability via the existingTEMP/TMPpath inresolved_permissions.resolve_windows_restricted_token_filesystem_overrides, compare writable roots using the same Windows-normalized root set the runtime already builds (stripSlashTmp/Tmpdir, remap temp) so protocol specials do not invent a second incompatible root set for the equality check alone.codex doctordiagnostic when unelevated + multi-root profile is still unenforceable for theapply_patch/ direct-FS path — today doctor does not probe create/update/delete under the selected backend.Alternatives considered (heavier or riskier):
write_roots_overridelike elevated (real capability/security review).apply_patchonly (inconsistent; hits elevated perf/setup issues from #32314 / #31220).Non-goals / do not weaken:
.git/.agents/.codexcarveouts.Happy to drop any of (1)–(3) if the team already has a preferred backend-side direction.
Test ideas
What should fail before / pass after if the team (or an invitee) implements:
PermissionProfile::workspace_write()with default temps included +WindowsSandboxLevel::RestrictedToken+ a layout whereAbsolutePathBuf("/tmp")exists as a directory →unsupported_windows_restricted_token_sandbox_reasonisNoneandresolve_windows_restricted_token_filesystem_overridesreturnsOk(_), not the split-root error.windows_restricted_token_allows_workspace_write_profilesto cover built-in defaults, not onlyexclude_* = true.:workspaceapply_patchcreate / update / delete of a disposable workspace file succeeds with no unsandboxed fallback; write outside workspace still denied.Questions for maintainers
:slash_tmp, align temp toTEMP/TMP), or in the unelevated backend (multi-rootwrite_roots_override)?C:\tmprequired to repro, or do other multi-root cases (extra--add-dir, plugins, Desktop viz roots as in #34970) hit the same equality check without it?codex doctorgrow anapply_patchcreate/update probe under the selected Windows backend?needs_direct_runtime_enforcementstays false, while only direct-FS tools fail?Please correct any of the above — especially if the team already treats Windows
:slash_tmpas intentional or has an in-flight elevated/unelevated redesign.Happy to refine this analysis with more pointers or a tighter repro matrix. If the team later wants an invited PR on an agreed approach, I’d be glad to help; no unsolicited PR from me.
Building on the root-cause analysis above with commit archaeology and a mechanism refinement for why
/tmpbecomesC:\tmpon Windows. Verified againstmainas of5dd992a(2026-07-24).Commit archaeology - where the platform divergence came from. The two divergent code paths were introduced at different times:
cfg!(unix)gate inprotocol.rs:1211is very old:git log -S "cfg!(unix)" -- codex-rs/protocol/src/protocol.rsreturnsd26224472/ #2355 (2025-08-15, "fix: introduce codex-protocol crate").SlashTmpresolver inpermissions.rscame with the permission-profile system:git log -S "SlashTmp" -- codex-rs/protocol/src/permissions.rsreturns #13434 (2026-03-06, "config: add initial support for the new permission profile config language"), #14174 (2026-03-12, "centralize filesystem permissions precedence"), and #19772 (2026-04-27, "permissions: derive config defaults as profiles").So the divergence emerged when the split policy added a platform-independent
SlashTmpalongside the oldercfg!(unix)legacy projection. On Windows the two disagree, andresolve_windows_restricted_token_filesystem_overrides(windows.rs:137-158) hard-errors when the legacy vs split rootBTreeSets differ. (Full history - not a shallow clone - shows these introducers. The policy-shape divergence is not a tip-of-mainregression - it dates to the 2026-03 permission-profile work; the hard-error equality check is from#14172(2026-03-24, restricted-token split carveouts), and it began to surface on direct-FS/apply_patchafter#28359(2026-06-17) ran the fs-helper through the Windows sandbox wrapper (also extracted intocodex-rs/sandboxing/src/windows.rs) - not from the elevated-sandbox#14568.)Mechanism refinement - why
/tmpbecomesC:\tmp. TheSlashTmpresolver is atpermissions.rs:1525-1531:FileSystemSpecialPath::SlashTmp => { let slash_tmp = AbsolutePathBuf::from_absolute_path("/tmp").expect("/tmp is absolute"); if !slash_tmp.as_path().is_dir() { return None; } Some(slash_tmp) }(the.expectis at:1527).AbsolutePathBuf::from_absolute_path("/tmp")(codex-rs/utils/absolute-path/src/lib.rs:58-61) callsabsolutize::absolutize(absolutize.rs:14); since/tmpis notis_absolute()on Windows (it has a root but no drive prefix),absolutizefalls back toabsolutize_from(path, std::env::current_dir()?)(absolutize.rs:19), and the Windowspath_with_base(absolutize.rs:57-59,#[cfg(windows)]) joins/tmponto that base becausepath.has_root()- yielding e.g.C:\tmp(the drive letter comes from the process's current directory; see the testwindows_root_relative_path_uses_base_prefixatabsolutize.rs:156). The.expect("/tmp is absolute")does not panic becauseabsolutizesucceeds. Caveat: this is source-level Windows path semantics, not a Windows runtime re-run on my side; the OP's list showsC:\tmp.Not fixed as of
5dd992a. All three divergent lines are unchanged; the most recent touches to these files through that tip (e.g.#34469, #34598, #34816, #34845, #34930, #35020, #35063) are unrelated to theSlashTmpplatform divergence.Test gap on the direct resolver.
resolve_windows_restricted_token_filesystem_overrideshas two direct callers inexec_tests.rs: insidewindows_restricted_token_supports_full_read_split_write_read_carveouts(call at:661, fn at:620) andwindows_restricted_token_rejects_unreadable_split_carveouts(call at:714, fn at:678). Both use customFileSystemSandboxPolicy::restricted(...)profiles (project-roots write plus extra read or deny carveouts), not the built-in:workspaceprofile. No unit test hitsresolve_windows_restricted_token_filesystem_overrides/ the legacy-vs-split equality check with built-in:workspacedefaults (temps included), leaving the equality-check divergence uncovered. A failing test would build a:workspaceprofile on Windows and assert the legacy vs split root sets agree (or that the restricted-token overlay does not hard-error on the resolved temps path).Reversible local mitigation experiment and rollback
Until the product defect is resolved, I plan to test whether narrowing the stock workspace temporary roots restores
apply_patchon native Windows. This is an experiment, not a proposed product fix.Before any change:
%USERPROFILE%\.codex\config.tomlto a timestamped adjacent backup.First phase:
sandbox_workspace_write.exclude_slash_tmp = truewithout changing the:tmpdirpolicy.C:\tmpcontent remains readable, a newC:\tmpwrite is denied or requires approval, and a normal%TEMP%temporary-file operation succeeds.apply_patchresult verbatim. This phase is not expected to remove the split root by itself because:tmpdirremains writable.Any experiment that also excludes or relocates
:tmpdirwill be reviewed separately. It must use only process-scoped or repository-scoped temporary storage and must not persistently rewrite Windows user-level or machine-levelTEMPorTMPvariables.Rollback:
%USERPROFILE%\.codex\config.tomlfrom the recorded backup.:slash_tmp, and:tmpdirwritable-root set has returned.The experiment will not delete, move, or repurpose
C:\tmp. The rollback therefore consists only of restoring one known configuration backup and starting a fresh session.Local mitigation implementation baseline
Owner authorization was given to complete the split-root workaround rather than stop after the diagnostic first phase.
Pre-change evidence:
0.145.0%USERPROFILE%\.codex\config.toml31D6EB92E359E15A8EFCA9F7AF050DF90C528075B1532D4209CBCEC9F85400FA%USERPROFILE%\.codex\config.toml.backup-20260724T155555Z31D6EB92E359E15A8EFCA9F7AF050DF90C528075B1532D4209CBCEC9F85400FATEMP/TMPvalues are unchanged.Exact planned configuration diff:
Both exclusions are required for this mitigation because retaining
:tmpdirwould retain a disjoint writable root. The next evidence comment will record the resulting configuration hash, effective fresh-session permissions, anapply_patchcreate/update/delete probe, standard Windows temporary-file behavior, and rollback readiness.Local mitigation implemented and verified
Final configuration:
Evidence:
8D7D97ED539559EA8F3FFA2AEA61C67FF9B02BDD53BB23AB8E08325515756B7E%USERPROFILE%\.codex\config.toml.backup-20260724T155555Z31D6EB92E359E15A8EFCA9F7AF050DF90C528075B1532D4209CBCEC9F85400FAcodex exec --ephemeral --strict-config --sandbox workspace-writestarted successfully with approvals disabled, proving the installed CLI accepted the configuration.file_changeevents for creating, updating, and deleting a disposable workspace file. The original split-rootapply_patcherror did not recur.%TEMP%and directC:\tmpwrite attempts were rejected by policy; neither external file was created.codex sandbox -P :workspacesuccessfully ran PowerShell and Git reads.UV_CACHE_DIR,TEMP, andTMPscoped to the repository for the command,uv run pytest tests/test_requirements_register.py -qcompleted:15 passed.TEMP/TMPconfiguration was not changed.Operational consequence: new Codex sessions now receive a workspace-only writable-root shape, which restores internal
apply_patch. Sandboxed tools that require temporary writes must use a workspace-local temporary directory or request explicit escalation; the normal external Windows temp location is no longer automatically writable.A pre-existing
.pytest_cacheACL produced one cache-write warning during the focused test, and the pre-existing.codex-tmp/tree remains unmodified. Neither was created by this mitigation.Exact rollback command:
After rollback, start a fresh Codex process and verify that the original SHA-256 and stock temporary writable roots return. Existing sessions retain the permission profile loaded at their own startup, so this mitigation likewise requires a fresh process before use.
Follow-on: disable login-shell profile loading under Constrained Language
After restarting into the workspace-only writable-root mitigation, shell commands began emitting this startup error:
Diagnosis:
ConstrainedLanguage.%USERPROFILE%\Documents\PowerShell\Microsoft.PowerShell_profile.ps1contains only conditional VS Code shell-integration initialization, which Codex CLI commands do not require.Owner-approved configuration diff:
The key will be inserted at the top level of
%USERPROFILE%\.codex\config.toml; the existing workspace-root exclusions remain unchanged.Pre-change evidence:
8D7D97ED539559EA8F3FFA2AEA61C67FF9B02BDD53BB23AB8E08325515756B7E%USERPROFILE%\.codex\config.toml.backup-20260724T165233Z-pre-no-login8D7D97ED539559EA8F3FFA2AEA61C67FF9B02BDD53BB23AB8E08325515756B7EPartial rollback for only this follow-on change is: restore the second-stage backup and start a fresh Codex process. The earlier full rollback remains available separately.
Follow-on no-login fix implemented and verified
Final added setting:
Evidence:
AFE00F2DDFFC10118698D2D9E40454D33AA751674BE26DF24EDB9F0A367DDD45codex exec --ephemeral --strict-config --sandbox workspace-writeprocess invoked the shell with the login parameter omitted.pwsh.exe -NoProfile.``
text
``LOGIN_PROFILE_PROBE_OK
LanguageMode=ConstrainedLanguage
Microsoft.PowerShell_profile.ps1error appeared.Partial rollback for only this follow-on change:
Start a fresh Codex process after rollback. The currently running parent conversation retains the configuration loaded at its startup, so its commands must continue to request non-login execution explicitly until that process is restarted.