diff --git a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs index e5b202dede..f0737ad8ba 100644 --- a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs +++ b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs @@ -22,18 +22,29 @@ pub(crate) const RESOURCES_DIRNAME: &str = "codex-resources"; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub(crate) enum HelperExecutable { CommandRunner, + WindowsSandboxSetup, } impl HelperExecutable { fn file_name(self) -> &'static str { match self { Self::CommandRunner => "codex-command-runner.exe", + Self::WindowsSandboxSetup => "codex-windows-sandbox-setup.exe", } } fn label(self) -> &'static str { match self { Self::CommandRunner => "command-runner", + Self::WindowsSandboxSetup => "windows-sandbox-setup", + } + } + + fn materialized_stem(self) -> &'static str { + match self { + Self::CommandRunner => "codex-command-runner", + // Avoid copied helper names that trigger Windows installer/UAC heuristics. + Self::WindowsSandboxSetup => "codex-windows-sandbox-helper", } } } @@ -220,10 +231,7 @@ fn helper_destination_for_source( fn materialized_file_name(kind: HelperExecutable, suffix: &str) -> String { let source_name = kind.file_name(); let path = Path::new(source_name); - let stem = path - .file_stem() - .and_then(|stem| stem.to_str()) - .unwrap_or(source_name); + let stem = kind.materialized_stem(); let extension = path .extension() .and_then(|ext| ext.to_str()) @@ -559,4 +567,12 @@ mod tests { assert_eq!(file_name, "codex-command-runner-test-suffix.exe"); } + + #[test] + fn setup_helper_materialized_name_avoids_setup_suffix() { + let file_name = + materialized_file_name(HelperExecutable::WindowsSandboxSetup, "test-suffix"); + + assert_eq!(file_name, "codex-windows-sandbox-helper-test-suffix.exe"); + } } diff --git a/codex-rs/windows-sandbox-rs/src/setup.rs b/codex-rs/windows-sandbox-rs/src/setup.rs index 428b5ff6a1..da3c0695be 100644 --- a/codex-rs/windows-sandbox-rs/src/setup.rs +++ b/codex-rs/windows-sandbox-rs/src/setup.rs @@ -12,8 +12,9 @@ use std::process::Stdio; use crate::allow::AllowDenyPaths; use crate::allow::compute_allow_paths_for_permissions; -use crate::helper_materialization::bundled_executable_path_for_exe; +use crate::helper_materialization::HelperExecutable; 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::current_log_file_path; use crate::logging::log_note; @@ -46,7 +47,6 @@ pub const ONLINE_USERNAME: &str = "CodexSandboxOnline"; const ERROR_CANCELLED: u32 = 1223; const SECURITY_BUILTIN_DOMAIN_RID: u32 = 0x0000_0020; const DOMAIN_ALIAS_RID_ADMINS: u32 = 0x0000_0220; -const SETUP_EXE_FILENAME: &str = "codex-windows-sandbox-setup.exe"; const USERPROFILE_ROOT_EXCLUSIONS: &[&str] = &[ ".ssh", ".tsh", @@ -209,7 +209,7 @@ fn run_setup_refresh_inner( }; let json = serde_json::to_vec(&payload)?; let b64 = BASE64_STANDARD.encode(json); - let exe = find_setup_exe(); + let exe = find_setup_exe(request.codex_home); let sbx_dir = sandbox_dir(request.codex_home); let log_path = current_log_file_path(&sbx_dir); let cleared_report = match clear_setup_error_report(request.codex_home) { @@ -662,17 +662,12 @@ fn quote_arg(arg: &str) -> String { out } -fn find_setup_exe() -> PathBuf { - if let Ok(exe) = std::env::current_exe() - && let Some(setup_exe) = find_setup_exe_for_current_exe(&exe) - { - return setup_exe; - } - PathBuf::from(SETUP_EXE_FILENAME) -} - -fn find_setup_exe_for_current_exe(exe: &Path) -> Option { - bundled_executable_path_for_exe(exe, SETUP_EXE_FILENAME) +fn find_setup_exe(codex_home: &Path) -> PathBuf { + resolve_helper_for_launch( + HelperExecutable::WindowsSandboxSetup, + codex_home, + Some(&sandbox_dir(codex_home)), + ) } fn report_helper_failure( @@ -716,7 +711,7 @@ fn run_setup_exe( use windows_sys::Win32::UI::Shell::SEE_MASK_NOCLOSEPROCESS; use windows_sys::Win32::UI::Shell::SHELLEXECUTEINFOW; use windows_sys::Win32::UI::Shell::ShellExecuteExW; - let exe = find_setup_exe(); + let exe = find_setup_exe(codex_home); let payload_json = serde_json::to_string(payload).map_err(|err| { failure( SetupErrorCode::OrchestratorPayloadSerializeFailed, @@ -1096,7 +1091,6 @@ fn filter_sensitive_write_roots(mut roots: Vec, codex_home: &Path) -> V mod tests { use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS; use super::build_payload_roots; - use super::find_setup_exe_for_current_exe; use super::gather_full_read_roots_for_permissions; use super::gather_read_roots; use super::loopback_proxy_port_from_url; @@ -1104,8 +1098,6 @@ mod tests { use super::profile_read_roots; use super::proxy_ports_from_env; use super::verify_setup_completed; - use crate::helper_materialization::BIN_DIRNAME; - use crate::helper_materialization::RESOURCES_DIRNAME; use crate::helper_materialization::helper_bin_dir; use crate::resolved_permissions::ResolvedWindowsSandboxPermissions; use crate::setup_error::SetupErrorCode; @@ -1281,24 +1273,6 @@ mod tests { ); } - #[test] - fn setup_exe_lookup_checks_package_resource_dir_for_bin_exe() { - let tmp = TempDir::new().expect("tempdir"); - let package_dir = tmp.path().join("package"); - let bin_dir = package_dir.join(BIN_DIRNAME); - let resources_dir = package_dir.join(RESOURCES_DIRNAME); - fs::create_dir_all(&bin_dir).expect("create bin dir"); - fs::create_dir_all(&resources_dir).expect("create resources dir"); - let exe = bin_dir.join("codex.exe"); - let setup_exe = resources_dir.join("codex-windows-sandbox-setup.exe"); - fs::write(&exe, b"codex").expect("write exe"); - fs::write(&setup_exe, b"setup").expect("write setup"); - - let resolved = find_setup_exe_for_current_exe(&exe).expect("setup exe"); - - assert_eq!(resolved, setup_exe); - } - #[test] fn loopback_proxy_url_parsing_rejects_non_loopback_and_zero_port() { assert_eq!(