From 9aaa5d9358b32b75cb9ff8c92bb6e5cba32d3fa8 Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Sat, 25 Apr 2026 16:23:58 -0700 Subject: [PATCH] [codex] Bypass managed network for escalated exec (#19595) ## Why `sandbox_permissions = "require_escalated"` is treated as an explicit request to approve the command and run it outside the filesystem/platform sandbox. Before this change, shell and unified exec still registered managed network approval context and could inject Codex-managed proxy state into the child process, which meant an approved escalated command could still hit a second network approval path. This PR makes that escalation boundary consistent: once a command is explicitly approved to run outside the sandbox, Codex does not also route that process through the managed network proxy. ## Security impact Command/filesystem sandbox approval now implies network approval for that command. If an untrusted command or script is allowed to run with `require_escalated`, its network calls are unsandboxed: Codex-managed network allowlists and denylists are not respected for that process, so the command can exfiltrate any data it can read. ## What changed - Skip managed network approval specs for `SandboxPermissions::RequireEscalated`. - Pass `network: None` into shell, zsh-fork shell, and unified exec sandbox preparation for explicitly escalated requests. - Strip Codex-managed proxy environment variables when `CODEX_NETWORK_PROXY_ACTIVE` is present, while preserving user proxy env when the Codex marker is absent. - Add regression coverage for the prepared exec request so the old behavior cannot silently reappear. ## Verification - `cargo test -p codex-core explicit_escalation` - `cargo clippy -p codex-core --all-targets -- -D warnings` --- codex-rs/core/src/tools/runtimes/mod.rs | 24 ++++ codex-rs/core/src/tools/runtimes/mod_tests.rs | 133 ++++++++++++++++++ codex-rs/core/src/tools/runtimes/shell.rs | 22 +-- .../tools/runtimes/shell/unix_escalation.rs | 17 ++- .../core/src/tools/runtimes/unified_exec.rs | 23 +-- codex-rs/core/src/tools/sandboxing.rs | 11 ++ 6 files changed, 204 insertions(+), 26 deletions(-) diff --git a/codex-rs/core/src/tools/runtimes/mod.rs b/codex-rs/core/src/tools/runtimes/mod.rs index a55f78f8a..073fda8ec 100644 --- a/codex-rs/core/src/tools/runtimes/mod.rs +++ b/codex-rs/core/src/tools/runtimes/mod.rs @@ -6,6 +6,7 @@ small and focused and reuses the orchestrator for approvals + sandbox + retry. */ use crate::exec_env::CODEX_THREAD_ID_ENV_VAR; use crate::path_utils; +use crate::sandboxing::SandboxPermissions; use crate::shell::Shell; use crate::tools::sandboxing::ToolError; #[cfg(target_os = "macos")] @@ -43,6 +44,29 @@ pub(crate) fn build_sandbox_command( }) } +pub(crate) fn exec_env_for_sandbox_permissions( + env: &HashMap, + sandbox_permissions: SandboxPermissions, +) -> HashMap { + let mut env = env.clone(); + if sandbox_permissions.requires_escalated_permissions() + && env.contains_key(PROXY_ACTIVE_ENV_KEY) + { + for key in PROXY_ENV_KEYS { + env.remove(*key); + } + // Only macOS injects a Codex-owned SSH wrapper for the managed SOCKS proxy. + #[cfg(target_os = "macos")] + if env + .get(PROXY_GIT_SSH_COMMAND_ENV_KEY) + .is_some_and(|command| command.starts_with(CODEX_PROXY_GIT_SSH_COMMAND_MARKER)) + { + env.remove(PROXY_GIT_SSH_COMMAND_ENV_KEY); + } + } + env +} + /// POSIX-only helper: for commands produced by `Shell::derive_exec_args` /// for Bash/Zsh/sh of the form `[shell_path, "-lc", "