From aca877b2d48b885c909cca0278160de700e25633 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Sun, 22 Mar 2026 18:37:47 -0700 Subject: [PATCH] Use current_exe for linux sandbox launches --- codex-rs/Cargo.lock | 1 + .../app-server/src/codex_message_processor.rs | 4 -- codex-rs/arg0/src/lib.rs | 25 +------- codex-rs/cli/src/debug_sandbox.rs | 49 +++------------ codex-rs/cli/src/main.rs | 21 ++----- codex-rs/cloud-tasks/src/lib.rs | 3 +- codex-rs/core/src/agent/role.rs | 1 - codex-rs/core/src/agent/role_tests.rs | 5 -- codex-rs/core/src/codex.rs | 7 --- codex-rs/core/src/codex_tests_guardian.rs | 2 - codex-rs/core/src/config/config_tests.rs | 4 -- codex-rs/core/src/config/mod.rs | 14 +---- codex-rs/core/src/connectors.rs | 1 - codex-rs/core/src/error.rs | 4 -- codex-rs/core/src/exec.rs | 8 +-- codex-rs/core/src/exec_tests.rs | 2 - codex-rs/core/src/guardian/review_session.rs | 2 - codex-rs/core/src/landlock.rs | 8 +-- codex-rs/core/src/mcp/mod.rs | 1 - codex-rs/core/src/mcp_connection_manager.rs | 1 - codex-rs/core/src/sandboxing/mod.rs | 10 ++-- codex-rs/core/src/sandboxing/mod_tests.rs | 3 - .../core/src/tools/handlers/apply_patch.rs | 2 - .../core/src/tools/handlers/multi_agents.rs | 1 - .../src/tools/handlers/multi_agents_tests.rs | 4 -- codex-rs/core/src/tools/js_repl/mod.rs | 1 - codex-rs/core/src/tools/orchestrator.rs | 2 - .../core/src/tools/runtimes/apply_patch.rs | 20 ++----- .../src/tools/runtimes/apply_patch_tests.rs | 1 - .../tools/runtimes/shell/unix_escalation.rs | 4 -- .../runtimes/shell/unix_escalation_tests.rs | 3 - codex-rs/core/src/tools/sandboxing.rs | 2 - codex-rs/core/tests/common/lib.rs | 60 +------------------ codex-rs/core/tests/common/test_codex.rs | 12 ---- codex-rs/core/tests/suite/exec.rs | 1 - codex-rs/exec/Cargo.toml | 1 + codex-rs/exec/src/lib.rs | 1 - codex-rs/exec/tests/suite/mod.rs | 45 ++++++++++++++ codex-rs/exec/tests/suite/sandbox.rs | 3 - .../linux-sandbox/tests/suite/landlock.rs | 6 -- codex-rs/mcp-server/src/codex_tool_config.rs | 1 - codex-rs/tui/src/lib.rs | 1 - codex-rs/tui_app_server/src/lib.rs | 1 - 43 files changed, 74 insertions(+), 274 deletions(-) diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index b3f8d88027..5b772e0dbe 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1985,6 +1985,7 @@ dependencies = [ "codex-utils-oss", "codex-utils-sandbox-summary", "core_test_support", + "ctor 0.6.3", "libc", "opentelemetry", "opentelemetry_sdk", diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 1b02e4bb6c..07bbb3a70c 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -518,7 +518,6 @@ impl CodexMessageProcessor { message: format!("failed to reload config: {err}"), data: None, })?; - config.codex_linux_sandbox_exe = self.arg0_paths.codex_linux_sandbox_exe.clone(); config.main_execve_wrapper_exe = self.arg0_paths.main_execve_wrapper_exe.clone(); Ok(config) } @@ -1731,7 +1730,6 @@ impl CodexMessageProcessor { ), }; - let codex_linux_sandbox_exe = self.arg0_paths.codex_linux_sandbox_exe.clone(); let outgoing = self.outgoing.clone(); let request_for_task = request.clone(); let started_network_proxy_for_task = started_network_proxy; @@ -1751,7 +1749,6 @@ impl CodexMessageProcessor { &effective_file_system_sandbox_policy, effective_network_sandbox_policy, sandbox_cwd.as_path(), - &codex_linux_sandbox_exe, use_legacy_landlock, ) { Ok(exec_request) => { @@ -2153,7 +2150,6 @@ impl CodexMessageProcessor { approvals_reviewer: approvals_reviewer .map(codex_app_server_protocol::ApprovalsReviewer::to_core), sandbox_mode: sandbox.map(SandboxMode::to_core), - codex_linux_sandbox_exe: self.arg0_paths.codex_linux_sandbox_exe.clone(), main_execve_wrapper_exe: self.arg0_paths.main_execve_wrapper_exe.clone(), base_instructions, developer_instructions, diff --git a/codex-rs/arg0/src/lib.rs b/codex-rs/arg0/src/lib.rs index d8dbaaa30d..7e568cecfd 100644 --- a/codex-rs/arg0/src/lib.rs +++ b/codex-rs/arg0/src/lib.rs @@ -19,7 +19,6 @@ const TOKIO_WORKER_STACK_SIZE_BYTES: usize = 16 * 1024 * 1024; #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Arg0DispatchPaths { - pub codex_linux_sandbox_exe: Option, pub main_execve_wrapper_exe: Option, } @@ -133,9 +132,7 @@ pub fn arg0_dispatch() -> Option { /// /// 1. Load `.env` values from `~/.codex/.env` before creating any threads. /// 2. Construct a Tokio multi-thread runtime. -/// 3. Derive the path to the current executable (so children can re-invoke the -/// sandbox) when running on Linux. -/// 4. Execute the provided async `main_fn` inside that runtime, forwarding any +/// 3. Execute the provided async `main_fn` inside that runtime, forwarding any /// error. Note that `main_fn` receives [`Arg0DispatchPaths`], which /// contains the helper executable paths needed to construct /// [`codex_core::config::Config`]. @@ -156,17 +153,7 @@ where // async entry-point. let runtime = build_runtime()?; runtime.block_on(async move { - let current_exe = std::env::current_exe().ok(); let paths = Arg0DispatchPaths { - codex_linux_sandbox_exe: if cfg!(target_os = "linux") { - current_exe.or_else(|| { - path_entry - .as_ref() - .and_then(|path_entry| path_entry.paths().codex_linux_sandbox_exe.clone()) - }) - } else { - None - }, main_execve_wrapper_exe: path_entry .as_ref() .and_then(|path_entry| path_entry.paths().main_execve_wrapper_exe.clone()), @@ -324,16 +311,6 @@ pub fn prepend_path_entry_for_codex_aliases() -> std::io::Result, -) -> anyhow::Result<()> { +pub async fn run_command_under_seatbelt(command: SeatbeltCommand) -> anyhow::Result<()> { let SeatbeltCommand { full_auto, log_denials, @@ -47,7 +44,6 @@ pub async fn run_command_under_seatbelt( full_auto, command, config_overrides, - codex_linux_sandbox_exe, SandboxType::Seatbelt, log_denials, ) @@ -55,17 +51,11 @@ pub async fn run_command_under_seatbelt( } #[cfg(not(target_os = "macos"))] -pub async fn run_command_under_seatbelt( - _command: SeatbeltCommand, - _codex_linux_sandbox_exe: Option, -) -> anyhow::Result<()> { +pub async fn run_command_under_seatbelt(_command: SeatbeltCommand) -> anyhow::Result<()> { anyhow::bail!("Seatbelt sandbox is only available on macOS"); } -pub async fn run_command_under_landlock( - command: LandlockCommand, - codex_linux_sandbox_exe: Option, -) -> anyhow::Result<()> { +pub async fn run_command_under_landlock(command: LandlockCommand) -> anyhow::Result<()> { let LandlockCommand { full_auto, config_overrides, @@ -75,17 +65,13 @@ pub async fn run_command_under_landlock( full_auto, command, config_overrides, - codex_linux_sandbox_exe, SandboxType::Landlock, /*log_denials*/ false, ) .await } -pub async fn run_command_under_windows( - command: WindowsCommand, - codex_linux_sandbox_exe: Option, -) -> anyhow::Result<()> { +pub async fn run_command_under_windows(command: WindowsCommand) -> anyhow::Result<()> { let WindowsCommand { full_auto, config_overrides, @@ -95,7 +81,6 @@ pub async fn run_command_under_windows( full_auto, command, config_overrides, - codex_linux_sandbox_exe, SandboxType::Windows, /*log_denials*/ false, ) @@ -113,7 +98,6 @@ async fn run_command_under_sandbox( full_auto: bool, command: Vec, config_overrides: CliConfigOverrides, - codex_linux_sandbox_exe: Option, sandbox_type: SandboxType, log_denials: bool, ) -> anyhow::Result<()> { @@ -121,7 +105,6 @@ async fn run_command_under_sandbox( config_overrides .parse_overrides() .map_err(anyhow::Error::msg)?, - codex_linux_sandbox_exe, full_auto, ) .await?; @@ -273,10 +256,6 @@ async fn run_command_under_sandbox( .await? } SandboxType::Landlock => { - #[expect(clippy::expect_used)] - let codex_linux_sandbox_exe = config - .codex_linux_sandbox_exe - .expect("codex-linux-sandbox executable not found"); let use_legacy_landlock = config.features.use_legacy_landlock(); let args = create_linux_sandbox_command_args_for_policies( command, @@ -290,7 +269,7 @@ async fn run_command_under_sandbox( ); let network_policy = config.permissions.network_sandbox_policy; spawn_debug_sandbox_child( - codex_linux_sandbox_exe, + std::env::current_exe()?, args, Some("codex-linux-sandbox"), cwd, @@ -373,30 +352,19 @@ async fn spawn_debug_sandbox_child( async fn load_debug_sandbox_config( cli_overrides: Vec<(String, TomlValue)>, - codex_linux_sandbox_exe: Option, full_auto: bool, ) -> anyhow::Result { - load_debug_sandbox_config_with_codex_home( - cli_overrides, - codex_linux_sandbox_exe, - full_auto, - /*codex_home*/ None, - ) - .await + load_debug_sandbox_config_with_codex_home(cli_overrides, full_auto, /*codex_home*/ None).await } async fn load_debug_sandbox_config_with_codex_home( cli_overrides: Vec<(String, TomlValue)>, - codex_linux_sandbox_exe: Option, full_auto: bool, codex_home: Option, ) -> anyhow::Result { let config = build_debug_sandbox_config( cli_overrides.clone(), - ConfigOverrides { - codex_linux_sandbox_exe: codex_linux_sandbox_exe.clone(), - ..Default::default() - }, + ConfigOverrides::default(), codex_home.clone(), ) .await?; @@ -414,7 +382,6 @@ async fn load_debug_sandbox_config_with_codex_home( cli_overrides, ConfigOverrides { sandbox_mode: Some(create_sandbox_mode(full_auto)), - codex_linux_sandbox_exe, ..Default::default() }, codex_home, @@ -505,7 +472,6 @@ mod tests { let config = load_debug_sandbox_config_with_codex_home( Vec::new(), - None, false, Some(codex_home_path), ) @@ -539,7 +505,6 @@ mod tests { let err = load_debug_sandbox_config_with_codex_home( Vec::new(), - None, true, Some(codex_home.path().to_path_buf()), ) diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 8446e457b2..01edb02ffe 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -783,8 +783,7 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> { &mut cloud_cli.config_overrides, root_config_overrides.clone(), ); - codex_cloud_tasks::run_main(cloud_cli, arg0_paths.codex_linux_sandbox_exe.clone()) - .await?; + codex_cloud_tasks::run_main(cloud_cli).await?; } Some(Subcommand::Sandbox(sandbox_args)) => match sandbox_args.cmd { SandboxCommand::Macos(mut seatbelt_cli) => { @@ -793,11 +792,7 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> { &mut seatbelt_cli.config_overrides, root_config_overrides.clone(), ); - codex_cli::debug_sandbox::run_command_under_seatbelt( - seatbelt_cli, - arg0_paths.codex_linux_sandbox_exe.clone(), - ) - .await?; + codex_cli::debug_sandbox::run_command_under_seatbelt(seatbelt_cli).await?; } SandboxCommand::Linux(mut landlock_cli) => { reject_remote_mode_for_subcommand(root_remote.as_deref(), "sandbox linux")?; @@ -805,11 +800,7 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> { &mut landlock_cli.config_overrides, root_config_overrides.clone(), ); - codex_cli::debug_sandbox::run_command_under_landlock( - landlock_cli, - arg0_paths.codex_linux_sandbox_exe.clone(), - ) - .await?; + codex_cli::debug_sandbox::run_command_under_landlock(landlock_cli).await?; } SandboxCommand::Windows(mut windows_cli) => { reject_remote_mode_for_subcommand(root_remote.as_deref(), "sandbox windows")?; @@ -817,11 +808,7 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> { &mut windows_cli.config_overrides, root_config_overrides.clone(), ); - codex_cli::debug_sandbox::run_command_under_windows( - windows_cli, - arg0_paths.codex_linux_sandbox_exe.clone(), - ) - .await?; + codex_cli::debug_sandbox::run_command_under_windows(windows_cli).await?; } }, Some(Subcommand::Debug(DebugCommand { subcommand })) => match subcommand { diff --git a/codex-rs/cloud-tasks/src/lib.rs b/codex-rs/cloud-tasks/src/lib.rs index c6abc80c10..efaa5361a4 100644 --- a/codex-rs/cloud-tasks/src/lib.rs +++ b/codex-rs/cloud-tasks/src/lib.rs @@ -15,7 +15,6 @@ use owo_colors::Stream; use std::cmp::Ordering; use std::io::IsTerminal; use std::io::Read; -use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use std::time::Instant; @@ -729,7 +728,7 @@ fn spawn_apply( // (no standalone patch summarizer needed – UI displays raw diffs) /// Entry point for the `codex cloud` subcommand. -pub async fn run_main(cli: Cli, _codex_linux_sandbox_exe: Option) -> anyhow::Result<()> { +pub async fn run_main(cli: Cli) -> anyhow::Result<()> { if let Some(command) = cli.command { return match command { crate::cli::Command::Exec(args) => run_exec_command(args).await, diff --git a/codex-rs/core/src/agent/role.rs b/codex-rs/core/src/agent/role.rs index 06c6eae1e6..0290950f67 100644 --- a/codex-rs/core/src/agent/role.rs +++ b/codex-rs/core/src/agent/role.rs @@ -254,7 +254,6 @@ mod reload { ConfigOverrides { cwd: Some(config.cwd.clone()), model_provider: preserve_current_provider.then(|| config.model_provider_id.clone()), - codex_linux_sandbox_exe: config.codex_linux_sandbox_exe.clone(), main_execve_wrapper_exe: config.main_execve_wrapper_exe.clone(), js_repl_node_path: config.js_repl_node_path.clone(), ..Default::default() diff --git a/codex-rs/core/src/agent/role_tests.rs b/codex-rs/core/src/agent/role_tests.rs index 7726ce7957..7d335fa605 100644 --- a/codex-rs/core/src/agent/role_tests.rs +++ b/codex-rs/core/src/agent/role_tests.rs @@ -160,7 +160,6 @@ async fn apply_role_preserves_unspecified_keys() { TomlValue::String("base-model".to_string()), )]) .await; - config.codex_linux_sandbox_exe = Some(PathBuf::from("/tmp/codex-linux-sandbox")); config.main_execve_wrapper_exe = Some(PathBuf::from("/tmp/codex-execve-wrapper")); let role_path = write_role_config( &home, @@ -183,10 +182,6 @@ async fn apply_role_preserves_unspecified_keys() { assert_eq!(config.model.as_deref(), Some("base-model")); assert_eq!(config.model_reasoning_effort, Some(ReasoningEffort::High)); - assert_eq!( - config.codex_linux_sandbox_exe, - Some(PathBuf::from("/tmp/codex-linux-sandbox")) - ); assert_eq!( config.main_execve_wrapper_exe, Some(PathBuf::from("/tmp/codex-execve-wrapper")) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 12270bb6dd..f537db002b 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -823,7 +823,6 @@ pub(crate) struct TurnContext { pub(crate) features: ManagedFeatures, pub(crate) ghost_snapshot: GhostSnapshotConfig, pub(crate) final_output_json_schema: Option, - pub(crate) codex_linux_sandbox_exe: Option, pub(crate) tool_call_gate: Arc, pub(crate) truncation_policy: TruncationPolicy, pub(crate) js_repl: Arc, @@ -930,7 +929,6 @@ impl TurnContext { features, ghost_snapshot: self.ghost_snapshot.clone(), final_output_json_schema: self.final_output_json_schema.clone(), - codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(), tool_call_gate: Arc::new(ReadinessFlag::new()), truncation_policy, js_repl: Arc::clone(&self.js_repl), @@ -1378,7 +1376,6 @@ impl Session { features: per_turn_config.features.clone(), ghost_snapshot: per_turn_config.ghost_snapshot.clone(), final_output_json_schema: None, - codex_linux_sandbox_exe: per_turn_config.codex_linux_sandbox_exe.clone(), tool_call_gate: Arc::new(ReadinessFlag::new()), truncation_policy: model_info.truncation_policy.into(), js_repl, @@ -1906,7 +1903,6 @@ impl Session { // MCP server immediately after it becomes ready (avoiding blocking). let sandbox_state = SandboxState { sandbox_policy: session_configuration.sandbox_policy.get().clone(), - codex_linux_sandbox_exe: config.codex_linux_sandbox_exe.clone(), sandbox_cwd: session_configuration.cwd.clone(), use_legacy_landlock: config.features.use_legacy_landlock(), }; @@ -2379,7 +2375,6 @@ impl Session { if sandbox_policy_changed { let sandbox_state = SandboxState { sandbox_policy: per_turn_config.permissions.sandbox_policy.get().clone(), - codex_linux_sandbox_exe: per_turn_config.codex_linux_sandbox_exe.clone(), sandbox_cwd: per_turn_config.cwd.clone(), use_legacy_landlock: per_turn_config.features.use_legacy_landlock(), }; @@ -4050,7 +4045,6 @@ impl Session { let auth_statuses = compute_auth_statuses(mcp_servers.iter(), store_mode).await; let sandbox_state = SandboxState { sandbox_policy: turn_context.sandbox_policy.get().clone(), - codex_linux_sandbox_exe: turn_context.codex_linux_sandbox_exe.clone(), sandbox_cwd: turn_context.cwd.clone(), use_legacy_landlock: turn_context.features.use_legacy_landlock(), }; @@ -5276,7 +5270,6 @@ async fn spawn_review_thread( shell_environment_policy: parent_turn_context.shell_environment_policy.clone(), cwd: parent_turn_context.cwd.clone(), final_output_json_schema: None, - codex_linux_sandbox_exe: parent_turn_context.codex_linux_sandbox_exe.clone(), tool_call_gate: Arc::new(ReadinessFlag::new()), js_repl: Arc::clone(&sess.js_repl), dynamic_tools: parent_turn_context.dynamic_tools.clone(), diff --git a/codex-rs/core/src/codex_tests_guardian.rs b/codex-rs/core/src/codex_tests_guardian.rs index af0fccc9ac..5a9d56bdfb 100644 --- a/codex-rs/core/src/codex_tests_guardian.rs +++ b/codex-rs/core/src/codex_tests_guardian.rs @@ -24,7 +24,6 @@ use codex_protocol::models::function_call_output_content_items_to_text; use codex_protocol::permissions::FileSystemSandboxPolicy; use codex_protocol::permissions::NetworkSandboxPolicy; use codex_utils_absolute_path::AbsolutePathBuf; -use core_test_support::codex_linux_sandbox_exe_or_skip; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_response_created; @@ -68,7 +67,6 @@ async fn guardian_allows_shell_additional_permissions_requests_past_policy_valid .await; let (mut session, mut turn_context_raw) = make_session_and_context().await; - turn_context_raw.codex_linux_sandbox_exe = codex_linux_sandbox_exe_or_skip!(); turn_context_raw .approval_policy .set(AskForApproval::OnRequest) diff --git a/codex-rs/core/src/config/config_tests.rs b/codex-rs/core/src/config/config_tests.rs index 1c78759ec4..f624fbc649 100644 --- a/codex-rs/core/src/config/config_tests.rs +++ b/codex-rs/core/src/config/config_tests.rs @@ -4298,7 +4298,6 @@ fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> { history: History::default(), ephemeral: false, file_opener: UriBasedFileOpener::VsCode, - codex_linux_sandbox_exe: None, main_execve_wrapper_exe: None, js_repl_node_path: None, js_repl_node_module_dirs: Vec::new(), @@ -4441,7 +4440,6 @@ fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> { history: History::default(), ephemeral: false, file_opener: UriBasedFileOpener::VsCode, - codex_linux_sandbox_exe: None, main_execve_wrapper_exe: None, js_repl_node_path: None, js_repl_node_module_dirs: Vec::new(), @@ -4582,7 +4580,6 @@ fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> { history: History::default(), ephemeral: false, file_opener: UriBasedFileOpener::VsCode, - codex_linux_sandbox_exe: None, main_execve_wrapper_exe: None, js_repl_node_path: None, js_repl_node_module_dirs: Vec::new(), @@ -4709,7 +4706,6 @@ fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> { history: History::default(), ephemeral: false, file_opener: UriBasedFileOpener::VsCode, - codex_linux_sandbox_exe: None, main_execve_wrapper_exe: None, js_repl_node_path: None, js_repl_node_module_dirs: Vec::new(), diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index 17abe55c46..e2ad24b58b 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -450,14 +450,6 @@ pub struct Config { /// output will be hyperlinked using the specified URI scheme. pub file_opener: UriBasedFileOpener, - /// Path to the `codex-linux-sandbox` executable. This must be set if - /// [`crate::exec::SandboxType::LinuxSeccomp`] is used. Note that this - /// cannot be set in the config file: it must be set in code via - /// [`ConfigOverrides`]. - /// - /// When this program is invoked, arg0 will be set to `codex-linux-sandbox`. - pub codex_linux_sandbox_exe: Option, - /// Path to the `codex-execve-wrapper` executable used for shell /// escalation. This cannot be set in the config file: it must be set in /// code via [`ConfigOverrides`]. @@ -846,8 +838,7 @@ impl Config { /// designed to use [AskForApproval::Never] exclusively. /// /// Further, [ConfigOverrides] contains some options that are not supported - /// in [ConfigToml], such as `cwd`, `codex_linux_sandbox_exe`, and - /// `main_execve_wrapper_exe`. + /// in [ConfigToml], such as `cwd` and `main_execve_wrapper_exe`. pub async fn load_with_cli_overrides_and_harness_overrides( cli_overrides: Vec<(String, TomlValue)>, harness_overrides: ConfigOverrides, @@ -1931,7 +1922,6 @@ pub struct ConfigOverrides { pub model_provider: Option, pub service_tier: Option>, pub config_profile: Option, - pub codex_linux_sandbox_exe: Option, pub main_execve_wrapper_exe: Option, pub js_repl_node_path: Option, pub js_repl_node_module_dirs: Option>, @@ -2129,7 +2119,6 @@ impl Config { model_provider, service_tier: service_tier_override, config_profile: config_profile_key, - codex_linux_sandbox_exe, main_execve_wrapper_exe, js_repl_node_path: js_repl_node_path_override, js_repl_node_module_dirs: js_repl_node_module_dirs_override, @@ -2730,7 +2719,6 @@ impl Config { history, ephemeral: ephemeral.unwrap_or_default(), file_opener: cfg.file_opener.unwrap_or(UriBasedFileOpener::VsCode), - codex_linux_sandbox_exe, main_execve_wrapper_exe, js_repl_node_path, js_repl_node_module_dirs, diff --git a/codex-rs/core/src/connectors.rs b/codex-rs/core/src/connectors.rs index 600ba9c6f9..ada616d037 100644 --- a/codex-rs/core/src/connectors.rs +++ b/codex-rs/core/src/connectors.rs @@ -211,7 +211,6 @@ pub async fn list_accessible_connectors_from_mcp_tools_with_options_and_status( let sandbox_state = SandboxState { sandbox_policy: SandboxPolicy::new_read_only_policy(), - codex_linux_sandbox_exe: config.codex_linux_sandbox_exe.clone(), sandbox_cwd: env::current_dir().unwrap_or_else(|_| PathBuf::from("/")), use_legacy_landlock: config.features.use_legacy_landlock(), }; diff --git a/codex-rs/core/src/error.rs b/codex-rs/core/src/error.rs index 80d60619dd..9fa9a4d29e 100644 --- a/codex-rs/core/src/error.rs +++ b/codex-rs/core/src/error.rs @@ -151,9 +151,6 @@ pub enum CodexErr { #[error("sandbox error: {0}")] Sandbox(#[from] SandboxErr), - #[error("codex-linux-sandbox was required but not provided")] - LandlockSandboxExecutableNotProvided, - #[error("unsupported operation: {0}")] UnsupportedOperation(String), @@ -207,7 +204,6 @@ impl CodexErr { | CodexErr::RefreshTokenFailed(_) | CodexErr::UnsupportedOperation(_) | CodexErr::Sandbox(_) - | CodexErr::LandlockSandboxExecutableNotProvided | CodexErr::RetryLimit(_) | CodexErr::ContextWindowExceeded | CodexErr::ThreadNotFound(_) diff --git a/codex-rs/core/src/exec.rs b/codex-rs/core/src/exec.rs index 9be0518fa0..eca086e30a 100644 --- a/codex-rs/core/src/exec.rs +++ b/codex-rs/core/src/exec.rs @@ -217,7 +217,6 @@ pub async fn process_exec_tool_call( file_system_sandbox_policy: &FileSystemSandboxPolicy, network_sandbox_policy: NetworkSandboxPolicy, sandbox_cwd: &Path, - codex_linux_sandbox_exe: &Option, use_legacy_landlock: bool, stdout_stream: Option, ) -> Result { @@ -227,7 +226,6 @@ pub async fn process_exec_tool_call( file_system_sandbox_policy, network_sandbox_policy, sandbox_cwd, - codex_linux_sandbox_exe, use_legacy_landlock, )?; @@ -243,7 +241,6 @@ pub fn build_exec_request( file_system_sandbox_policy: &FileSystemSandboxPolicy, network_sandbox_policy: NetworkSandboxPolicy, sandbox_cwd: &Path, - codex_linux_sandbox_exe: &Option, use_legacy_landlock: bool, ) -> Result { let windows_sandbox_level = params.windows_sandbox_level; @@ -304,7 +301,6 @@ pub fn build_exec_request( sandbox_policy_cwd: sandbox_cwd, #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions: None, - codex_linux_sandbox_exe: codex_linux_sandbox_exe.as_ref(), use_legacy_landlock, windows_sandbox_level, windows_sandbox_private_desktop, @@ -625,9 +621,7 @@ pub(crate) mod errors { impl From for CodexErr { fn from(err: SandboxTransformError) -> Self { match err { - SandboxTransformError::MissingLinuxSandboxExecutable => { - CodexErr::LandlockSandboxExecutableNotProvided - } + SandboxTransformError::CurrentExecutableUnavailable(err) => CodexErr::Io(err), #[cfg(not(target_os = "macos"))] SandboxTransformError::SeatbeltUnavailable => CodexErr::UnsupportedOperation( "seatbelt sandbox is only available on macOS".to_string(), diff --git a/codex-rs/core/src/exec_tests.rs b/codex-rs/core/src/exec_tests.rs index fc312ec88e..9a572e0a9d 100644 --- a/codex-rs/core/src/exec_tests.rs +++ b/codex-rs/core/src/exec_tests.rs @@ -358,7 +358,6 @@ async fn process_exec_tool_call_preserves_full_buffer_capture_policy() -> Result &FileSystemSandboxPolicy::from(&sandbox_policy), NetworkSandboxPolicy::Enabled, cwd.as_path(), - &None, false, None, ) @@ -662,7 +661,6 @@ async fn process_exec_tool_call_respects_cancellation_token() -> Result<()> { &FileSystemSandboxPolicy::from(&SandboxPolicy::DangerFullAccess), NetworkSandboxPolicy::Enabled, cwd.as_path(), - &None, false, None, ) diff --git a/codex-rs/core/src/guardian/review_session.rs b/codex-rs/core/src/guardian/review_session.rs index 34f0b6298e..f4df32cda1 100644 --- a/codex-rs/core/src/guardian/review_session.rs +++ b/codex-rs/core/src/guardian/review_session.rs @@ -115,7 +115,6 @@ struct GuardianReviewSessionReuseKey { compact_prompt: Option, cwd: PathBuf, mcp_servers: Constrained>, - codex_linux_sandbox_exe: Option, main_execve_wrapper_exe: Option, js_repl_node_path: Option, js_repl_node_module_dirs: Vec, @@ -142,7 +141,6 @@ impl GuardianReviewSessionReuseKey { compact_prompt: spawn_config.compact_prompt.clone(), cwd: spawn_config.cwd.clone(), mcp_servers: spawn_config.mcp_servers.clone(), - codex_linux_sandbox_exe: spawn_config.codex_linux_sandbox_exe.clone(), main_execve_wrapper_exe: spawn_config.main_execve_wrapper_exe.clone(), js_repl_node_path: spawn_config.js_repl_node_path.clone(), js_repl_node_module_dirs: spawn_config.js_repl_node_module_dirs.clone(), diff --git a/codex-rs/core/src/landlock.rs b/codex-rs/core/src/landlock.rs index 19b3f7c6af..07a912dc62 100644 --- a/codex-rs/core/src/landlock.rs +++ b/codex-rs/core/src/landlock.rs @@ -20,7 +20,6 @@ use tokio::process::Child; /// incrementally without breaking older call sites. #[allow(clippy::too_many_arguments)] pub async fn spawn_command_under_linux_sandbox

( - codex_linux_sandbox_exe: P, command: Vec, command_cwd: PathBuf, sandbox_policy: &SandboxPolicy, @@ -29,10 +28,7 @@ pub async fn spawn_command_under_linux_sandbox

( stdio_policy: StdioPolicy, network: Option<&NetworkProxy>, env: HashMap, -) -> std::io::Result -where - P: AsRef, -{ +) -> std::io::Result { let file_system_sandbox_policy = FileSystemSandboxPolicy::from_legacy_sandbox_policy(sandbox_policy, sandbox_policy_cwd); let network_sandbox_policy = NetworkSandboxPolicy::from(sandbox_policy); @@ -48,7 +44,7 @@ where ); let arg0 = Some("codex-linux-sandbox"); spawn_child_async(SpawnChildRequest { - program: codex_linux_sandbox_exe.as_ref().to_path_buf(), + program: std::env::current_exe()?, args, arg0, cwd: command_cwd, diff --git a/codex-rs/core/src/mcp/mod.rs b/codex-rs/core/src/mcp/mod.rs index 81ee0c7fe8..707efaf7f9 100644 --- a/codex-rs/core/src/mcp/mod.rs +++ b/codex-rs/core/src/mcp/mod.rs @@ -277,7 +277,6 @@ pub async fn collect_mcp_snapshot(config: &Config) -> McpListToolsResponseEvent // Use ReadOnly sandbox policy for MCP snapshot collection (safest default) let sandbox_state = SandboxState { sandbox_policy: SandboxPolicy::new_read_only_policy(), - codex_linux_sandbox_exe: config.codex_linux_sandbox_exe.clone(), sandbox_cwd: env::current_dir().unwrap_or_else(|_| PathBuf::from("/")), use_legacy_landlock: config.features.use_legacy_landlock(), }; diff --git a/codex-rs/core/src/mcp_connection_manager.rs b/codex-rs/core/src/mcp_connection_manager.rs index 938d6d0b2b..5f0ffdbe19 100644 --- a/codex-rs/core/src/mcp_connection_manager.rs +++ b/codex-rs/core/src/mcp_connection_manager.rs @@ -588,7 +588,6 @@ pub const MCP_SANDBOX_STATE_METHOD: &str = "codex/sandbox-state/update"; #[serde(rename_all = "camelCase")] pub struct SandboxState { pub sandbox_policy: SandboxPolicy, - pub codex_linux_sandbox_exe: Option, pub sandbox_cwd: PathBuf, #[serde(default)] pub use_legacy_landlock: bool, diff --git a/codex-rs/core/src/sandboxing/mod.rs b/codex-rs/core/src/sandboxing/mod.rs index 277ff2b241..9d43b1081f 100644 --- a/codex-rs/core/src/sandboxing/mod.rs +++ b/codex-rs/core/src/sandboxing/mod.rs @@ -97,7 +97,6 @@ pub(crate) struct SandboxTransformRequest<'a> { pub sandbox_policy_cwd: &'a Path, #[cfg(target_os = "macos")] pub macos_seatbelt_profile_extensions: Option<&'a MacOsSeatbeltProfileExtensions>, - pub codex_linux_sandbox_exe: Option<&'a PathBuf>, pub use_legacy_landlock: bool, pub windows_sandbox_level: WindowsSandboxLevel, pub windows_sandbox_private_desktop: bool, @@ -111,8 +110,8 @@ pub enum SandboxPreference { #[derive(Debug, thiserror::Error)] pub(crate) enum SandboxTransformError { - #[error("missing codex-linux-sandbox executable path")] - MissingLinuxSandboxExecutable, + #[error("failed to resolve current executable for linux sandbox launch: {0}")] + CurrentExecutableUnavailable(std::io::Error), #[cfg(not(target_os = "macos"))] #[error("seatbelt sandbox is only available on macOS")] SeatbeltUnavailable, @@ -595,7 +594,6 @@ impl SandboxManager { sandbox_policy_cwd, #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions, - codex_linux_sandbox_exe, use_legacy_landlock, windows_sandbox_level, windows_sandbox_private_desktop, @@ -670,8 +668,8 @@ impl SandboxManager { #[cfg(not(target_os = "macos"))] SandboxType::MacosSeatbelt => return Err(SandboxTransformError::SeatbeltUnavailable), SandboxType::LinuxSeccomp => { - let exe = codex_linux_sandbox_exe - .ok_or(SandboxTransformError::MissingLinuxSandboxExecutable)?; + let exe = std::env::current_exe() + .map_err(SandboxTransformError::CurrentExecutableUnavailable)?; let allow_proxy_network = allow_network_for_proxy(enforce_managed_network); let mut args = create_linux_sandbox_command_args_for_policies( command.clone(), diff --git a/codex-rs/core/src/sandboxing/mod_tests.rs b/codex-rs/core/src/sandboxing/mod_tests.rs index 9a7a34e49d..f36b4fdaea 100644 --- a/codex-rs/core/src/sandboxing/mod_tests.rs +++ b/codex-rs/core/src/sandboxing/mod_tests.rs @@ -174,7 +174,6 @@ fn transform_preserves_unrestricted_file_system_policy_for_restricted_network() sandbox_policy_cwd: cwd.as_path(), #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions: None, - codex_linux_sandbox_exe: None, use_legacy_landlock: false, windows_sandbox_level: WindowsSandboxLevel::Disabled, windows_sandbox_private_desktop: false, @@ -544,7 +543,6 @@ fn transform_additional_permissions_enable_network_for_external_sandbox() { sandbox_policy_cwd: cwd.as_path(), #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions: None, - codex_linux_sandbox_exe: None, use_legacy_landlock: false, windows_sandbox_level: WindowsSandboxLevel::Disabled, windows_sandbox_private_desktop: false, @@ -618,7 +616,6 @@ fn transform_additional_permissions_preserves_denied_entries() { sandbox_policy_cwd: cwd.as_path(), #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions: None, - codex_linux_sandbox_exe: None, use_legacy_landlock: false, windows_sandbox_level: WindowsSandboxLevel::Disabled, windows_sandbox_private_desktop: false, diff --git a/codex-rs/core/src/tools/handlers/apply_patch.rs b/codex-rs/core/src/tools/handlers/apply_patch.rs index 1d799da7e7..edca67daae 100644 --- a/codex-rs/core/src/tools/handlers/apply_patch.rs +++ b/codex-rs/core/src/tools/handlers/apply_patch.rs @@ -206,7 +206,6 @@ impl ToolHandler for ApplyPatchHandler { permissions_preapproved: effective_additional_permissions .permissions_preapproved, timeout_ms: None, - codex_exe: turn.codex_linux_sandbox_exe.clone(), }; let mut orchestrator = ToolOrchestrator::new(); @@ -310,7 +309,6 @@ pub(crate) async fn intercept_apply_patch( permissions_preapproved: effective_additional_permissions .permissions_preapproved, timeout_ms, - codex_exe: turn.codex_linux_sandbox_exe.clone(), }; let mut orchestrator = ToolOrchestrator::new(); diff --git a/codex-rs/core/src/tools/handlers/multi_agents.rs b/codex-rs/core/src/tools/handlers/multi_agents.rs index 897af0d5f0..1f81dad3c6 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents.rs @@ -305,7 +305,6 @@ fn apply_spawn_agent_runtime_overrides( FunctionCallError::RespondToModel(format!("approval_policy is invalid: {err}")) })?; config.permissions.shell_environment_policy = turn.shell_environment_policy.clone(); - config.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone(); config.cwd = turn.cwd.clone(); config .permissions diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs index d8b2a713a5..9c22e93670 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs @@ -28,7 +28,6 @@ use pretty_assertions::assert_eq; use serde::Deserialize; use serde_json::json; use std::collections::HashMap; -use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use tokio::sync::Mutex; @@ -1552,7 +1551,6 @@ async fn build_agent_spawn_config_uses_turn_context_values() { }; let temp_dir = tempfile::tempdir().expect("temp dir"); turn.cwd = temp_dir.path().to_path_buf(); - turn.codex_linux_sandbox_exe = Some(PathBuf::from("/bin/echo")); let sandbox_policy = pick_allowed_sandbox_policy( &turn.config.permissions.sandbox_policy, turn.config.permissions.sandbox_policy.get().clone(), @@ -1579,7 +1577,6 @@ async fn build_agent_spawn_config_uses_turn_context_values() { expected.developer_instructions = turn.developer_instructions.clone(); expected.compact_prompt = turn.compact_prompt.clone(); expected.permissions.shell_environment_policy = turn.shell_environment_policy.clone(); - expected.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone(); expected.cwd = turn.cwd.clone(); expected .permissions @@ -1633,7 +1630,6 @@ async fn build_agent_resume_config_clears_base_instructions() { expected.developer_instructions = turn.developer_instructions.clone(); expected.compact_prompt = turn.compact_prompt.clone(); expected.permissions.shell_environment_policy = turn.shell_environment_policy.clone(); - expected.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone(); expected.cwd = turn.cwd.clone(); expected .permissions diff --git a/codex-rs/core/src/tools/js_repl/mod.rs b/codex-rs/core/src/tools/js_repl/mod.rs index 4f7c3d7436..44c2f3cf02 100644 --- a/codex-rs/core/src/tools/js_repl/mod.rs +++ b/codex-rs/core/src/tools/js_repl/mod.rs @@ -1070,7 +1070,6 @@ impl JsReplManager { sandbox_policy_cwd: &turn.cwd, #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions: None, - codex_linux_sandbox_exe: turn.codex_linux_sandbox_exe.as_ref(), use_legacy_landlock: turn.features.use_legacy_landlock(), windows_sandbox_level: turn.windows_sandbox_level, windows_sandbox_private_desktop: turn diff --git a/codex-rs/core/src/tools/orchestrator.rs b/codex-rs/core/src/tools/orchestrator.rs index 4b53ac156f..2c4af61882 100644 --- a/codex-rs/core/src/tools/orchestrator.rs +++ b/codex-rs/core/src/tools/orchestrator.rs @@ -199,7 +199,6 @@ impl ToolOrchestrator { enforce_managed_network: has_managed_network_requirements, manager: &self.sandbox, sandbox_cwd: &turn_ctx.cwd, - codex_linux_sandbox_exe: turn_ctx.codex_linux_sandbox_exe.as_ref(), use_legacy_landlock, windows_sandbox_level: turn_ctx.windows_sandbox_level, windows_sandbox_private_desktop: turn_ctx @@ -330,7 +329,6 @@ impl ToolOrchestrator { enforce_managed_network: has_managed_network_requirements, manager: &self.sandbox, sandbox_cwd: &turn_ctx.cwd, - codex_linux_sandbox_exe: None, use_legacy_landlock, windows_sandbox_level: turn_ctx.windows_sandbox_level, windows_sandbox_private_desktop: turn_ctx diff --git a/codex-rs/core/src/tools/runtimes/apply_patch.rs b/codex-rs/core/src/tools/runtimes/apply_patch.rs index f1e9912bc5..838da96490 100644 --- a/codex-rs/core/src/tools/runtimes/apply_patch.rs +++ b/codex-rs/core/src/tools/runtimes/apply_patch.rs @@ -43,7 +43,6 @@ pub struct ApplyPatchRequest { pub additional_permissions: Option, pub permissions_preapproved: bool, pub timeout_ms: Option, - pub codex_exe: Option, } #[derive(Default)] @@ -71,20 +70,11 @@ impl ApplyPatchRuntime { req: &ApplyPatchRequest, _codex_home: &std::path::Path, ) -> Result { - let exe = if let Some(path) = &req.codex_exe { - path.clone() - } else { - #[cfg(target_os = "windows")] - { - codex_windows_sandbox::resolve_current_exe_for_launch(_codex_home, "codex.exe") - } - #[cfg(not(target_os = "windows"))] - { - std::env::current_exe().map_err(|e| { - ToolError::Rejected(format!("failed to determine codex exe: {e}")) - })? - } - }; + #[cfg(target_os = "windows")] + let exe = codex_windows_sandbox::resolve_current_exe_for_launch(_codex_home, "codex.exe"); + #[cfg(not(target_os = "windows"))] + let exe = std::env::current_exe() + .map_err(|e| ToolError::Rejected(format!("failed to determine codex exe: {e}")))?; let program = exe.to_string_lossy().to_string(); Ok(CommandSpec { program, diff --git a/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs b/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs index d2812b5ecf..688c93a3ac 100644 --- a/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs +++ b/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs @@ -52,7 +52,6 @@ fn guardian_review_request_includes_patch_context() { additional_permissions: None, permissions_preapproved: false, timeout_ms: None, - codex_exe: None, }; let guardian_request = ApplyPatchRuntime::build_guardian_review_request(&request, "call-1"); diff --git a/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs b/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs index 948018dae6..f513674d56 100644 --- a/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs +++ b/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs @@ -164,7 +164,6 @@ pub(super) async fn try_run_zsh_fork( .permissions .macos_seatbelt_profile_extensions .clone(), - codex_linux_sandbox_exe: ctx.turn.codex_linux_sandbox_exe.clone(), use_legacy_landlock: ctx.turn.features.use_legacy_landlock(), }; let main_execve_wrapper_exe = ctx @@ -270,7 +269,6 @@ pub(crate) async fn prepare_unified_exec_zsh_fork( .permissions .macos_seatbelt_profile_extensions .clone(), - codex_linux_sandbox_exe: ctx.turn.codex_linux_sandbox_exe.clone(), use_legacy_landlock: ctx.turn.features.use_legacy_landlock(), }; let escalation_policy = CoreShellActionProvider { @@ -863,7 +861,6 @@ struct CoreShellCommandExecutor { sandbox_policy_cwd: PathBuf, #[cfg_attr(not(target_os = "macos"), allow(dead_code))] macos_seatbelt_profile_extensions: Option, - codex_linux_sandbox_exe: Option, use_legacy_landlock: bool, } @@ -1063,7 +1060,6 @@ impl CoreShellCommandExecutor { sandbox_policy_cwd: &self.sandbox_policy_cwd, #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions, - codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.as_ref(), use_legacy_landlock: self.use_legacy_landlock, windows_sandbox_level: self.windows_sandbox_level, windows_sandbox_private_desktop: false, diff --git a/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs b/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs index 37c1b53a13..93093bae75 100644 --- a/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs +++ b/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs @@ -668,7 +668,6 @@ async fn prepare_escalated_exec_turn_default_preserves_macos_seatbelt_extensions macos_preferences: MacOsPreferencesPermission::ReadWrite, ..Default::default() }), - codex_linux_sandbox_exe: None, use_legacy_landlock: false, }; @@ -717,7 +716,6 @@ async fn prepare_escalated_exec_permissions_preserve_macos_seatbelt_extensions() arg0: None, sandbox_policy_cwd: cwd.to_path_buf(), macos_seatbelt_profile_extensions: None, - codex_linux_sandbox_exe: None, use_legacy_landlock: false, }; @@ -795,7 +793,6 @@ async fn prepare_escalated_exec_permission_profile_unions_turn_and_requested_mac macos_preferences: MacOsPreferencesPermission::ReadOnly, ..Default::default() }), - codex_linux_sandbox_exe: None, use_legacy_landlock: false, }; diff --git a/codex-rs/core/src/tools/sandboxing.rs b/codex-rs/core/src/tools/sandboxing.rs index bf386a12d0..adf8b5505c 100644 --- a/codex-rs/core/src/tools/sandboxing.rs +++ b/codex-rs/core/src/tools/sandboxing.rs @@ -330,7 +330,6 @@ pub(crate) struct SandboxAttempt<'a> { pub enforce_managed_network: bool, pub(crate) manager: &'a SandboxManager, pub(crate) sandbox_cwd: &'a Path, - pub codex_linux_sandbox_exe: Option<&'a std::path::PathBuf>, pub use_legacy_landlock: bool, pub windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel, pub windows_sandbox_private_desktop: bool, @@ -354,7 +353,6 @@ impl<'a> SandboxAttempt<'a> { sandbox_policy_cwd: self.sandbox_cwd, #[cfg(target_os = "macos")] macos_seatbelt_profile_extensions: None, - codex_linux_sandbox_exe: self.codex_linux_sandbox_exe, use_legacy_landlock: self.use_legacy_landlock, windows_sandbox_level: self.windows_sandbox_level, windows_sandbox_private_desktop: self.windows_sandbox_private_desktop, diff --git a/codex-rs/core/tests/common/lib.rs b/codex-rs/core/tests/common/lib.rs index 0b31793402..e0e55ace4a 100644 --- a/codex-rs/core/tests/common/lib.rs +++ b/codex-rs/core/tests/common/lib.rs @@ -162,12 +162,7 @@ pub async fn load_default_config_for_test(codex_home: &TempDir) -> Config { #[cfg(target_os = "linux")] fn default_test_overrides() -> ConfigOverrides { - ConfigOverrides { - codex_linux_sandbox_exe: Some( - find_codex_linux_sandbox_exe().expect("should find binary for codex-linux-sandbox"), - ), - ..ConfigOverrides::default() - } + ConfigOverrides::default() } #[cfg(not(target_os = "linux"))] @@ -175,23 +170,6 @@ fn default_test_overrides() -> ConfigOverrides { ConfigOverrides::default() } -#[cfg(target_os = "linux")] -pub fn find_codex_linux_sandbox_exe() -> Result { - if let Ok(path) = std::env::current_exe() { - return Ok(path); - } - - if let Some(path) = TEST_ARG0_PATH_ENTRY - .get() - .and_then(Option::as_ref) - .and_then(|path_entry| path_entry.paths().codex_linux_sandbox_exe.clone()) - { - return Ok(path); - } - - codex_utils_cargo_bin::cargo_bin("codex-linux-sandbox") -} - /// Builds an SSE stream body from a JSON fixture. /// /// The fixture must contain an array of objects where each object represents a @@ -525,42 +503,6 @@ macro_rules! skip_if_no_network { }}; } -#[macro_export] -macro_rules! codex_linux_sandbox_exe_or_skip { - () => {{ - #[cfg(target_os = "linux")] - { - match $crate::find_codex_linux_sandbox_exe() { - Ok(path) => Some(path), - Err(err) => { - eprintln!("codex-linux-sandbox binary not available, skipping test: {err}"); - return; - } - } - } - #[cfg(not(target_os = "linux"))] - { - None - } - }}; - ($return_value:expr $(,)?) => {{ - #[cfg(target_os = "linux")] - { - match $crate::find_codex_linux_sandbox_exe() { - Ok(path) => Some(path), - Err(err) => { - eprintln!("codex-linux-sandbox binary not available, skipping test: {err}"); - return $return_value; - } - } - } - #[cfg(not(target_os = "linux"))] - { - None - } - }}; -} - #[macro_export] macro_rules! skip_if_windows { ($return_value:expr $(,)?) => {{ diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index 6df93bcd85..d6f2a5b39f 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -561,18 +561,6 @@ impl TestCodexBuilder { for hook in self.pre_build_hooks.drain(..) { hook(home.path()); } - if let Ok(path) = codex_utils_cargo_bin::cargo_bin("codex") { - config.codex_linux_sandbox_exe = Some(path); - } else if let Ok(exe) = std::env::current_exe() - && let Some(path) = exe - .parent() - .and_then(|parent| parent.parent()) - .map(|parent| parent.join("codex")) - && path.is_file() - { - config.codex_linux_sandbox_exe = Some(path); - } - let mut mutators = vec![]; swap(&mut self.config_mutators, &mut mutators); for mutator in mutators { diff --git a/codex-rs/core/tests/suite/exec.rs b/codex-rs/core/tests/suite/exec.rs index 069e824ee5..815144edb6 100644 --- a/codex-rs/core/tests/suite/exec.rs +++ b/codex-rs/core/tests/suite/exec.rs @@ -56,7 +56,6 @@ async fn run_test_cmd(tmp: TempDir, cmd: Vec<&str>) -> Result anyhow::Result cwd: resolved_cwd, model_provider: model_provider.clone(), service_tier: None, - codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(), main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(), js_repl_node_path: None, js_repl_node_module_dirs: None, diff --git a/codex-rs/exec/tests/suite/mod.rs b/codex-rs/exec/tests/suite/mod.rs index d86d079774..13e57ab88e 100644 --- a/codex-rs/exec/tests/suite/mod.rs +++ b/codex-rs/exec/tests/suite/mod.rs @@ -1,4 +1,49 @@ // Aggregates all former standalone integration tests as modules. +use codex_arg0::Arg0PathEntryGuard; +use codex_arg0::arg0_dispatch; +use ctor::ctor; +use tempfile::TempDir; + +struct TestCodexAliasesGuard { + _codex_home: TempDir, + _arg0: Arg0PathEntryGuard, +} + +const CODEX_HOME_ENV_VAR: &str = "CODEX_HOME"; + +// This code runs before any other tests are run. +// It allows the test binary to behave like codex-exec and dispatch to +// codex-linux-sandbox based on the arg0. +#[ctor] +pub static CODEX_ALIASES_TEMP_DIR: TestCodexAliasesGuard = unsafe { + #[allow(clippy::unwrap_used)] + let codex_home = tempfile::Builder::new() + .prefix("codex-exec-tests") + .tempdir() + .unwrap(); + let previous_codex_home = std::env::var_os(CODEX_HOME_ENV_VAR); + + // Safety: #[ctor] runs before test threads start. + unsafe { + std::env::set_var(CODEX_HOME_ENV_VAR, codex_home.path()); + } + #[allow(clippy::unwrap_used)] + let arg0 = arg0_dispatch().unwrap(); + match previous_codex_home.as_ref() { + Some(value) => unsafe { + std::env::set_var(CODEX_HOME_ENV_VAR, value); + }, + None => unsafe { + std::env::remove_var(CODEX_HOME_ENV_VAR); + }, + } + + TestCodexAliasesGuard { + _codex_home: codex_home, + _arg0: arg0, + } +}; + mod add_dir; mod apply_patch; mod auth_env; diff --git a/codex-rs/exec/tests/suite/sandbox.rs b/codex-rs/exec/tests/suite/sandbox.rs index e6dd37927b..9d17696a48 100644 --- a/codex-rs/exec/tests/suite/sandbox.rs +++ b/codex-rs/exec/tests/suite/sandbox.rs @@ -43,10 +43,7 @@ async fn spawn_command_under_sandbox( env: HashMap, ) -> std::io::Result { use codex_core::landlock::spawn_command_under_linux_sandbox; - let codex_linux_sandbox_exe = codex_utils_cargo_bin::cargo_bin("codex-exec") - .map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?; spawn_command_under_linux_sandbox( - codex_linux_sandbox_exe, command, command_cwd, sandbox_policy, diff --git a/codex-rs/linux-sandbox/tests/suite/landlock.rs b/codex-rs/linux-sandbox/tests/suite/landlock.rs index 8e273783b8..e53d33d2c2 100644 --- a/codex-rs/linux-sandbox/tests/suite/landlock.rs +++ b/codex-rs/linux-sandbox/tests/suite/landlock.rs @@ -126,8 +126,6 @@ async fn run_cmd_result_with_policies( justification: None, arg0: None, }; - let sandbox_program = env!("CARGO_BIN_EXE_codex-linux-sandbox"); - let codex_linux_sandbox_exe = Some(PathBuf::from(sandbox_program)); process_exec_tool_call( params, @@ -135,7 +133,6 @@ async fn run_cmd_result_with_policies( &file_system_sandbox_policy, network_sandbox_policy, sandbox_cwd.as_path(), - &codex_linux_sandbox_exe, use_legacy_landlock, None, ) @@ -388,15 +385,12 @@ async fn assert_network_blocked(cmd: &[&str]) { }; let sandbox_policy = SandboxPolicy::new_read_only_policy(); - let sandbox_program = env!("CARGO_BIN_EXE_codex-linux-sandbox"); - let codex_linux_sandbox_exe: Option = Some(PathBuf::from(sandbox_program)); let result = process_exec_tool_call( params, &sandbox_policy, &FileSystemSandboxPolicy::from(&sandbox_policy), NetworkSandboxPolicy::from(&sandbox_policy), sandbox_cwd.as_path(), - &codex_linux_sandbox_exe, false, None, ) diff --git a/codex-rs/mcp-server/src/codex_tool_config.rs b/codex-rs/mcp-server/src/codex_tool_config.rs index f3f66b5559..fa7aae9d7d 100644 --- a/codex-rs/mcp-server/src/codex_tool_config.rs +++ b/codex-rs/mcp-server/src/codex_tool_config.rs @@ -176,7 +176,6 @@ impl CodexToolCallParam { cwd: cwd.map(PathBuf::from), approval_policy: approval_policy.map(Into::into), sandbox_mode: sandbox.map(Into::into), - codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(), main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(), base_instructions, developer_instructions, diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index 5416200691..6211ed6271 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -416,7 +416,6 @@ pub async fn run_main( cwd, model_provider: model_provider_override.clone(), config_profile: cli.config_profile.clone(), - codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(), main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(), show_raw_agent_reasoning: cli.oss.then_some(true), additional_writable_roots: additional_dirs, diff --git a/codex-rs/tui_app_server/src/lib.rs b/codex-rs/tui_app_server/src/lib.rs index 17e309d5fb..3cb1cf88b5 100644 --- a/codex-rs/tui_app_server/src/lib.rs +++ b/codex-rs/tui_app_server/src/lib.rs @@ -738,7 +738,6 @@ pub async fn run_main( cwd, model_provider: model_provider_override.clone(), config_profile: cli.config_profile.clone(), - codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(), main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(), show_raw_agent_reasoning: cli.oss.then_some(true), additional_writable_roots: additional_dirs,