codex - ✅(Solved) Fix Sandboxed apply_patch falls back to vendored bwrap because exec-server fs helper clears PATH [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openai/codex#18185Fetched 2026-04-17 08:31:42
View on GitHub
Comments
1
Participants
2
Timeline
9
Reactions
0
Author
Timeline (top)
labeled ×4cross-referenced ×3commented ×1unlabeled ×1

Sandboxed apply_patch can fall back to vendored bubblewrap when it runs through the exec-server filesystem sandbox helper. In environments where the system bwrap binary must be used, for example Ubuntu setups relying on AppArmor policy for /usr/bin/bwrap, this breaks sandboxed filesystem operations such as apply_patch.

Error Message

I dont know how else you could see this, except if you change the code to throw an error when it tries to use the vendored one (which would be a nice setting to have. reject_vendored_bwrap=true).

Root Cause

The filesystem sandbox helper path introduced in d626dc3 launches the helper with an empty env map in SandboxCommand { env: HashMap::new(), ... }.

Later, spawn_command(...) in codex-rs/exec-server/src/fs_sandbox.rs does:

  • command.env_clear()
  • command.envs(env)

So the helper process gets no PATH.

Later, Linux sandbox launcher selection in preferred_bwrap_launcher() uses find_system_bwrap_in_path(). Since PATH is missing in this helper process, system bwrap lookup fails and the code falls back to vendored bubblewrap.

Fix Action

Fix / Workaround

Sandboxed apply_patch can fall back to vendored bubblewrap when it runs through the exec-server filesystem sandbox helper. In environments where the system bwrap binary must be used, for example Ubuntu setups relying on AppArmor policy for /usr/bin/bwrap, this breaks sandboxed filesystem operations such as apply_patch.

  • sandboxed shell command execution works
  • apply_patch fails under sandbox
  • AppArmor logs show the helper going through the codex-linux-sandbox path instead of /usr/bin/bwrap
  • the helper then attempts to create a user namespace
  • AppArmor rejects the namespace setup under the unprivileged_userns profile

If you run codex sandboxed with bwrap from system (/usr/bin/bwrap) and ask it to use apply_patch, it should fall back to using the vendored bwrap for that.

PR fix notes

PR #18296: fix: fix fs sandbox helper for apply_patch

Description (problem / solution / changelog)

Summary

  • pass split filesystem sandbox policy/cwd through apply_patch contexts, while omitting legacy-equivalent policies to keep payloads small
  • keep the fs helper compatible with legacy Landlock by avoiding helper read-root permission expansion in that mode and disabling helper network access

Root Cause

d626dc38950fb40a1a5ad0a8ffab2485e3348c53 routed exec-server filesystem operations through a sandboxed helper. That path forwarded legacy Landlock into a helper policy shape that could require direct split-policy enforcement. Sandboxed apply_patch hit that edge through the filesystem abstraction.

The same 0.121 edit-regression path is consistent with #18354: normal writes route through the apply_patch filesystem helper, fail under sandbox, and then surface the generic retry-without-sandbox prompt.

Fixes #18069 Fixes #18354

Validation

  • cd codex-rs && just fmt
  • earlier branch validation before merging current origin/main and dropping the now-separate PATH fix:
    • cd codex-rs && cargo test -p codex-exec-server
    • cd codex-rs && cargo test -p codex-core file_system_sandbox_context
    • cd codex-rs && just fix -p codex-exec-server
    • cd codex-rs && just fix -p codex-core
    • git diff --check
    • cd codex-rs && cargo clean

Changed files

  • codex-rs/core/src/session/turn_context.rs (modified, +16/-13)
  • codex-rs/core/src/tools/runtimes/apply_patch.rs (modified, +11/-0)
  • codex-rs/core/src/tools/runtimes/apply_patch_tests.rs (modified, +55/-1)
  • codex-rs/exec-server/src/file_system.rs (modified, +7/-0)
  • codex-rs/exec-server/src/fs_sandbox.rs (modified, +170/-51)

Code Example

diff --git a/codex-rs/exec-server/src/fs_sandbox.rs b/codex-rs/exec-server/src/fs_sandbox.rs
index 7b0ac25..3ed6c57 100644
--- a/codex-rs/exec-server/src/fs_sandbox.rs
+++ b/codex-rs/exec-server/src/fs_sandbox.rs
@@ -81,11 +81,14 @@ impl FileSystemSandboxRunner {
             sandbox_context.windows_sandbox_level,
             /*has_managed_network_requirements*/ false,
         );
+        let path_env = std::env::var_os("PATH")
+            .map(|path| HashMap::from([("PATH".to_string(), path.to_string_lossy().into_owned())]))
+            .unwrap_or_default();
         let command = SandboxCommand {
             program: helper.as_path().as_os_str().to_owned(),
             args: vec![CODEX_FS_HELPER_ARG1.to_string()],
             cwd: cwd.clone(),
-            env: HashMap::new(),
+            env: path_env,
             additional_permissions: Some(
                 self.helper_permissions(sandbox_context.additional_permissions.as_ref()),
             ),
RAW_BUFFERClick to expand / collapse

What version of Codex CLI is running?

0.120.0

What subscription do you have?

plus

Which model were you using?

gpt-5.4

What platform is your computer?

Ubuntu 24.04

What terminal emulator and version are you using (if applicable)?

wezterm

What issue are you seeing?

Summary

Sandboxed apply_patch can fall back to vendored bubblewrap when it runs through the exec-server filesystem sandbox helper. In environments where the system bwrap binary must be used, for example Ubuntu setups relying on AppArmor policy for /usr/bin/bwrap, this breaks sandboxed filesystem operations such as apply_patch.

What I observed

On my setup:

  • sandboxed shell command execution works
  • apply_patch fails under sandbox
  • AppArmor logs show the helper going through the codex-linux-sandbox path instead of /usr/bin/bwrap
  • the helper then attempts to create a user namespace
  • AppArmor rejects the namespace setup under the unprivileged_userns profile

What steps can reproduce the bug?

If you run codex sandboxed with bwrap from system (/usr/bin/bwrap) and ask it to use apply_patch, it should fall back to using the vendored bwrap for that.

I can see it because it fails and asks for permission to run it outside the sandbox. And then in kern.log, i see that apparmor rejects the vendored tools attempt to create a user namespace.

I dont know how else you could see this, except if you change the code to throw an error when it tries to use the vendored one (which would be a nice setting to have. reject_vendored_bwrap=true).

What is the expected behavior?

Codex started under /usr/bin/bwrap, should keep using that.

Additional information

Root cause

The filesystem sandbox helper path introduced in d626dc3 launches the helper with an empty env map in SandboxCommand { env: HashMap::new(), ... }.

Later, spawn_command(...) in codex-rs/exec-server/src/fs_sandbox.rs does:

  • command.env_clear()
  • command.envs(env)

So the helper process gets no PATH.

Later, Linux sandbox launcher selection in preferred_bwrap_launcher() uses find_system_bwrap_in_path(). Since PATH is missing in this helper process, system bwrap lookup fails and the code falls back to vendored bubblewrap.

Proposed solution

Preserve only PATH from the parent process when spawning the exec-server fs sandbox helper, while keeping the rest of the helper environment cleared.

diff --git a/codex-rs/exec-server/src/fs_sandbox.rs b/codex-rs/exec-server/src/fs_sandbox.rs
index 7b0ac25..3ed6c57 100644
--- a/codex-rs/exec-server/src/fs_sandbox.rs
+++ b/codex-rs/exec-server/src/fs_sandbox.rs
@@ -81,11 +81,14 @@ impl FileSystemSandboxRunner {
             sandbox_context.windows_sandbox_level,
             /*has_managed_network_requirements*/ false,
         );
+        let path_env = std::env::var_os("PATH")
+            .map(|path| HashMap::from([("PATH".to_string(), path.to_string_lossy().into_owned())]))
+            .unwrap_or_default();
         let command = SandboxCommand {
             program: helper.as_path().as_os_str().to_owned(),
             args: vec![CODEX_FS_HELPER_ARG1.to_string()],
             cwd: cwd.clone(),
-            env: HashMap::new(),
+            env: path_env,
             additional_permissions: Some(
                 self.helper_permissions(sandbox_context.additional_permissions.as_ref()),
             ),

With that patch:

  • sandboxed apply_patch succeeds again
  • writes outside the allowed sandbox roots still trigger the normal sandbox and approval behavior
  • targeted tests pass:
    • cargo test -p codex-exec-server
    • cargo test -p codex-linux-sandbox

extent analysis

TL;DR

The issue can be fixed by preserving the PATH environment variable when spawning the exec-server fs sandbox helper, allowing the system bwrap binary to be used instead of the vendored one.

Guidance

  • The root cause of the issue is the empty env map in the SandboxCommand struct, which prevents the system bwrap binary from being found.
  • To verify the issue, run codex sandboxed with bwrap from the system (/usr/bin/bwrap) and attempt to use apply_patch, which should fail and prompt for permission to run outside the sandbox.
  • To mitigate the issue, apply the proposed patch to preserve the PATH environment variable when spawning the exec-server fs sandbox helper.
  • Test the fix by running targeted tests, such as cargo test -p codex-exec-server and cargo test -p codex-linux-sandbox.

Example

The proposed patch is provided in the issue body, which modifies the fs_sandbox.rs file to preserve the PATH environment variable:

let path_env = std::env::var_os("PATH")
    .map(|path| HashMap::from([("PATH".to_string(), path.to_string_lossy().into_owned())]))
    .unwrap_or_default();
let command = SandboxCommand {
    program: helper.as_path().as_os_str().to_owned(),
    args: vec![CODEX_FS_HELPER_ARG1.to_string()],
    cwd: cwd.clone(),
    env: path_env,
    additional_permissions: Some(
        self.helper_permissions(sandbox_context.additional_permissions.as_ref()),
    ),

Notes

The proposed solution only preserves the PATH environment variable, while keeping the rest of the helper environment cleared, to ensure that the system bwrap binary is used instead of the vendored one.

Recommendation

Apply the proposed patch to preserve the PATH environment variable when spawning the exec-server fs sandbox helper, as it fixes the issue and allows the system bwrap binary to be used.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING