From d0a0ad6f2f3b3acaab997b77595ad3da5ba71233 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Wed, 3 Jun 2026 17:08:58 -0700 Subject: [PATCH] windows-sandbox: materialize setup helper before launch --- .../src/helper_materialization.rs | 10 ++++++++++ codex-rs/windows-sandbox-rs/src/setup.rs | 18 +++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs index e5b202dede..b06c6c81f8 100644 --- a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs +++ b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs @@ -22,18 +22,21 @@ pub(crate) const RESOURCES_DIRNAME: &str = "codex-resources"; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub(crate) enum HelperExecutable { CommandRunner, + SetupHelper, } impl HelperExecutable { fn file_name(self) -> &'static str { match self { Self::CommandRunner => "codex-command-runner.exe", + Self::SetupHelper => "codex-windows-sandbox-setup.exe", } } fn label(self) -> &'static str { match self { Self::CommandRunner => "command-runner", + Self::SetupHelper => "setup-helper", } } } @@ -559,4 +562,11 @@ mod tests { assert_eq!(file_name, "codex-command-runner-test-suffix.exe"); } + + #[test] + fn setup_helper_materialized_file_name_adds_suffix_before_extension() { + let file_name = materialized_file_name(HelperExecutable::SetupHelper, "test-suffix"); + + assert_eq!(file_name, "codex-windows-sandbox-setup-test-suffix.exe"); + } } diff --git a/codex-rs/windows-sandbox-rs/src/setup.rs b/codex-rs/windows-sandbox-rs/src/setup.rs index c1881b55c8..363620a65c 100644 --- a/codex-rs/windows-sandbox-rs/src/setup.rs +++ b/codex-rs/windows-sandbox-rs/src/setup.rs @@ -12,8 +12,10 @@ use std::process::Stdio; use crate::allow::AllowDenyPaths; use crate::allow::compute_allow_paths_for_permissions; +use crate::helper_materialization::HelperExecutable; use crate::helper_materialization::bundled_executable_path_for_exe; use crate::helper_materialization::helper_bin_dir; +use crate::helper_materialization::resolve_helper_for_launch; use crate::identity::sandbox_setup_is_complete; use crate::logging::log_note; use crate::path_normalization::canonical_path_key; @@ -209,8 +211,14 @@ fn run_setup_refresh_inner( }; let json = serde_json::to_vec(&payload)?; let b64 = BASE64_STANDARD.encode(json); - let exe = find_setup_exe(); - // Refresh should never request elevation; ensure verb isn't set and we don't trigger UAC. + let log_dir = sandbox_dir(request.codex_home); + let exe = resolve_helper_for_launch( + HelperExecutable::SetupHelper, + request.codex_home, + Some(&log_dir), + ); + // Refresh should never request elevation, so prefer a copied helper path + // instead of launching the packaged setup executable directly. let mut cmd = Command::new(&exe); cmd.arg(&b64).stdout(Stdio::null()).stderr(Stdio::null()); let cwd = std::env::current_dir().unwrap_or_else(|_| request.codex_home.to_path_buf()); @@ -221,14 +229,14 @@ fn run_setup_refresh_inner( cwd.display(), b64.len() ), - Some(&sandbox_dir(request.codex_home)), + Some(&log_dir), ); let status = cmd .status() .map_err(|e| { log_note( &format!("setup refresh: failed to spawn {}: {e}", exe.display()), - Some(&sandbox_dir(request.codex_home)), + Some(&log_dir), ); e }) @@ -236,7 +244,7 @@ fn run_setup_refresh_inner( if !status.success() { log_note( &format!("setup refresh: exited with status {status:?}"), - Some(&sandbox_dir(request.codex_home)), + Some(&log_dir), ); return Err(anyhow!("setup refresh failed with status {status}")); }