diff --git a/codex-rs/linux-sandbox/README.md b/codex-rs/linux-sandbox/README.md index b03919c96..32d8d99f0 100644 --- a/codex-rs/linux-sandbox/README.md +++ b/codex-rs/linux-sandbox/README.md @@ -25,7 +25,8 @@ into this binary. - When enabled, symlink-in-path and non-existent protected paths inside writable roots are blocked by mounting `/dev/null` on the symlink or first missing component. -- When enabled, the helper isolates the PID namespace via `--unshare-pid`. +- When enabled, the helper explicitly isolates the user namespace via + `--unshare-user` and the PID namespace via `--unshare-pid`. - When enabled and network is restricted without proxy routing, the helper also isolates the network namespace via `--unshare-net`. - In managed proxy mode, the helper uses `--unshare-net` plus an internal diff --git a/codex-rs/linux-sandbox/src/bwrap.rs b/codex-rs/linux-sandbox/src/bwrap.rs index 56c4ce70d..783c3a428 100644 --- a/codex-rs/linux-sandbox/src/bwrap.rs +++ b/codex-rs/linux-sandbox/src/bwrap.rs @@ -107,6 +107,9 @@ fn create_bwrap_flags_full_filesystem(command: Vec, options: BwrapOption "--bind".to_string(), "/".to_string(), "/".to_string(), + // Always enter a fresh user namespace so root inside a container does + // not need ambient CAP_SYS_ADMIN to create the remaining namespaces. + "--unshare-user".to_string(), "--unshare-pid".to_string(), ]; if options.network_mode.should_unshare_network() { @@ -132,6 +135,9 @@ fn create_bwrap_flags( args.push("--new-session".to_string()); args.push("--die-with-parent".to_string()); args.extend(create_filesystem_args(sandbox_policy, cwd)?); + // Request a user namespace explicitly rather than relying on bubblewrap's + // auto-enable behavior, which is skipped when the caller runs as uid 0. + args.push("--unshare-user".to_string()); // Isolate the PID namespace. args.push("--unshare-pid".to_string()); if options.network_mode.should_unshare_network() { @@ -425,6 +431,7 @@ mod tests { "--bind".to_string(), "/".to_string(), "/".to_string(), + "--unshare-user".to_string(), "--unshare-pid".to_string(), "--unshare-net".to_string(), "--proc".to_string(), diff --git a/codex-rs/linux-sandbox/src/linux_run_main_tests.rs b/codex-rs/linux-sandbox/src/linux_run_main_tests.rs index 11471afbe..cda509030 100644 --- a/codex-rs/linux-sandbox/src/linux_run_main_tests.rs +++ b/codex-rs/linux-sandbox/src/linux_run_main_tests.rs @@ -49,6 +49,7 @@ fn inserts_bwrap_argv0_before_command_separator() { "/".to_string(), "--dev".to_string(), "/dev".to_string(), + "--unshare-user".to_string(), "--unshare-pid".to_string(), "--proc".to_string(), "/proc".to_string(),