apply_patch can modify files outside writable roots without an approval prompt
What version of Codex CLI is running?
codex-cli 0.142.5
What subscription do you have?
ChatGPT Plus
Which model were you using?
gpt-5.4
What platform is your computer?
Linux 6.18.33.2-microsoft-standard-WSL2 x86_64 x86_64
What terminal emulator and version are you using (if applicable)?
VS Code integrated terminal on WSL2 (TERM_PROGRAM=vscode). No tmux/zellij.
Codex doctor report
not collected yet
What issue are you seeing?
I observed a filesystem permission-boundary bypass involving the built-in patch/edit path.
In a session running with a workspace-write style sandbox and restricted writable roots, Codex successfully modified ~/.bashrc by appending a block of shell functions, even though ~/.bashrc was outside the declared writable roots and no approval prompt was shown.
The important point is not just that a file outside the workspace was modified, but that the write happened through the patch/edit path with zero approval despite the path being outside the allowed writable roots.
In the same environment, shell-based access to the same target path would normally require escalated approval. So this appears to be inconsistent enforcement between the patch/edit path and normal command execution.
Observed result:
~/.bashrcwas modified successfully- no approval prompt was shown
- the target path was outside the writable roots for the session
Expected result:
- the patch should have been blocked, or
- Codex should have requested explicit approval before applying it
What steps can reproduce the bug?
- Start Codex CLI in a repository with a restricted workspace-write environment where home-directory dotfiles are outside the writable roots.
- Confirm the writable roots do not include the user home directory or
~/.bashrc. - Ask Codex to inspect
~/.bashrcand then append a small shell alias/function block to the end of the file. - Observe that the patch/edit succeeds without an approval dialog.
- Compare this with normal shell behavior against the same path, which should require escalated approval in the same environment.
Repro details from the affected session:
- target file:
~/.bashrc - sandbox mode: workspace-write style restricted environment
- writable roots did not include the home directory
- the write succeeded anyway with no approval prompt
If useful, I can provide a redacted transcript excerpt showing:
- the declared writable roots
- the successful patch result
- the target path outside those roots
What is the expected behavior?
Writes outside the writable roots should not succeed silently through the patch/edit path.
Approval enforcement should be consistent across:
- built-in patch/edit operations
- shell command writes
- other file mutation paths
If a target file is outside the writable roots, Codex should either block the operation or require explicit approval before applying it.
Additional information
This may be related to prior sandbox / out-of-workspace enforcement reports, but it is not an exact duplicate because this case specifically involves the patch/edit path succeeding on a home-directory dotfile outside writable roots:
- #5203 Sandbox allowed unauthorized out-of-workspace operations despite restrictions
- #11583 Codex bypasses workspace restrictions, edits in other folders with 0 permission requests
- #17018 Sandbox policy inconsistency: Git metadata writes bypass approval after repo root relocation
- #29627 Agent cancels pending manual approvals automatically and treats them as unapproved instead of waiting
3 Comments
I ran an additional safe control using a temp file instead of a home dotfile.
Environment:
codex-cli 0.142.5Darwin arm64workspace-writenever, and also checkedon-requestforapply_patch/tmp/.../outside-*.txt, outside the temp workspaceexclude_tmpdir_env_var=trueandexclude_slash_tmp=trueResult:
operation not permittedapply_patchto the outside target was rejected withpatch rejected: writing outside of the project; rejected by user approval settingsapply_patchwas rejected the same waySo I could not reproduce the silent
apply_patchwrite in this macOS control. That does not rule out the original WSL/Linux report, but it narrows the next checks.The normal safety path appears to reject or request approval for out-of-root patches, and existing tests cover that expectation. The paths I would check next are:
core/src/tools/handlers/apply_patch.rscore/src/tools/handlers/mod.rscore/src/tools/runtimes/apply_patch.rsNoneor hit a path URI / native path matching edge caseA focused regression test could drive an out-of-writable-root target through both the native
apply_patchtool path and intercepted shellapply_patch <<...path, asserting that it either requests approval or rejects, and never writes silently.I will not open a PR unless maintainers ask, but I can prepare that local regression test/patch if this direction is useful.
I discovered similar behavior in both the Codex CLI
0.148.0and VS Code extension26.818.22352(runtime0.148.0-alpha.21) in my WSL2 instance today (Ubuntu26.04)Reproduction
Setup
Two fresh Git repositories,
AandB, side by side in onedirectory. The directory sits outside every writable location the
session has (not under
/tmp, which workspace-write allows bydefault).
Bcontainsoutside.mdat its top level.Case 1: VS Code extension, no extra grants
Aas the workspace and start a Codex chat.A(plus defaults) aswritable.
B/outside.md. The patch runs asapply_patchinvoked through theexectool.Result: the write to
B/outside.mdlands. No approval promptappears. In the same session, a nested patch to a different
Bfilewas rejected, so enforcement on this route is inconsistent, not
absent.
Case 2: CLI, explicit workspace-write with one extra root
Awithsandbox_mode = "workspace-write"andonly
B/.scratchadded as an extra writable root.B/outside.md— a path under no writableroot.
Result: the shell route writes the file. No approval prompt appears.
Why it matters
Users read the writable-roots list as the boundary of what an agent
session can change. Both interfaces crossed that boundary silently.
Anyone who relies on the sandbox to confine an agent to its project —
for example when the neighboring directory is another repository — is
not protected today.
Related case: unauthorized side-effect outside the task's declared storage boundary.
Environment: Linux NUC, Codex local task, NAS-backed NFS mount at /mnt/mainpool. The shared operating policy explicitly marked /mnt/mainpool and the NAS host read-only unless the user separately authorized a specific mutation.
A prior Codex CD-ripping task had authorization to work in /mnt/downloads/workspace and to create one explicitly named Galgame album destination. It nevertheless created an additional output tree under:
/mnt/mainpool/Audio/音樂/Converted/project lights/
The created files were two FLAC CD-image outputs plus CUE/LOG/AccurateRip/artifacts. Their logs identified the actor as a Codex audio CD extraction workflow. The user had not authorized the Converted destination or the duplicate outputs.
Expected:
Actual:
This is related to the path-enforcement issue, but the important distinction is agent instruction/authorization enforcement: a task should not infer authorization to write arbitrary sibling output directories merely because the process has OS-level write access. A machine-checkable per-task allowed-path guard or mandatory approval for any path outside the approved target would have prevented this.
No secrets or private file contents are included.