apply_patch can modify files outside writable roots without an approval prompt

Open 💬 3 comments Opened Jul 7, 2026 by Alek2077

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:

  • ~/.bashrc was 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?

  1. Start Codex CLI in a repository with a restricted workspace-write environment where home-directory dotfiles are outside the writable roots.
  2. Confirm the writable roots do not include the user home directory or ~/.bashrc.
  3. Ask Codex to inspect ~/.bashrc and then append a small shell alias/function block to the end of the file.
  4. Observe that the patch/edit succeeds without an approval dialog.
  5. 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

View original on GitHub ↗

3 Comments

DAWNCR0W · 1 month ago

I ran an additional safe control using a temp file instead of a home dotfile.

Environment:

  • codex-cli 0.142.5
  • Darwin arm64
  • sandbox: workspace-write
  • approval: never, and also checked on-request for apply_patch
  • target path: /tmp/.../outside-*.txt, outside the temp workspace
  • config included exclude_tmpdir_env_var=true and exclude_slash_tmp=true

Result:

  • shell write to the outside target was blocked with operation not permitted
  • native apply_patch to the outside target was rejected with patch rejected: writing outside of the project; rejected by user approval settings
  • shell heredoc apply_patch was rejected the same way
  • no outside target files were created

So I could not reproduce the silent apply_patch write 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:

  • effective permission calculation and the path-matching fallback in core/src/tools/handlers/apply_patch.rs
  • preapproved granted permissions in core/src/tools/handlers/mod.rs
  • approval short-circuit behavior in core/src/tools/runtimes/apply_patch.rs
  • whether the affected WSL/Linux session resolved the runtime sandbox as None or hit a path URI / native path matching edge case

A focused regression test could drive an out-of-writable-root target through both the native apply_patch tool path and intercepted shell apply_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.

ItsJPrentice · 7 days ago

I discovered similar behavior in both the Codex CLI 0.148.0 and VS Code extension 26.818.22352 (runtime 0.148.0-alpha.21) in my WSL2 instance today (Ubuntu 26.04)

Reproduction

Setup

Two fresh Git repositories, A and B, side by side in one
directory. The directory sits outside every writable location the
session has (not under /tmp, which workspace-write allows by
default). B contains outside.md at its top level.

Case 1: VS Code extension, no extra grants

  1. Open A as the workspace and start a Codex chat.
  2. Confirm the turn context lists only A (plus defaults) as

writable.

  1. Ask the agent to patch B/outside.md. The patch runs as

apply_patch invoked through the exec tool.

Result: the write to B/outside.md lands. No approval prompt
appears. In the same session, a nested patch to a different B file
was rejected, so enforcement on this route is inconsistent, not
absent.

Case 2: CLI, explicit workspace-write with one extra root

  1. Launch the CLI in A with sandbox_mode = "workspace-write" and

only B/.scratch added as an extra writable root.

  1. Ask for a shell edit of B/outside.md — a path under no writable

root.

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.

sky683 · 5 days ago

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:

  • Treat the policy boundary as blocking.
  • Keep extraction outputs in the approved workspace.
  • Ask before writing any other NAS/main-library path.

Actual:

  • The task wrote to the NFS-mounted main media path without an explicit approval for that target.
  • The OS mount was rw and the local UID had write ACLs, so prose/policy instructions were the only effective guard.
  • The task later required manual quarantine cleanup.

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.