diff --git a/codex-rs/core/src/tools/runtimes/apply_patch.rs b/codex-rs/core/src/tools/runtimes/apply_patch.rs index 208c78c722..91993ecd1d 100644 --- a/codex-rs/core/src/tools/runtimes/apply_patch.rs +++ b/codex-rs/core/src/tools/runtimes/apply_patch.rs @@ -46,13 +46,26 @@ impl ApplyPatchRuntime { Self } - fn build_command_spec(req: &ApplyPatchRequest) -> Result { - use std::env; + fn build_command_spec( + req: &ApplyPatchRequest, + codex_home: &std::path::Path, + ) -> Result { let exe = if let Some(path) = &req.codex_exe { path.clone() } else { - env::current_exe() - .map_err(|e| ToolError::Rejected(format!("failed to determine codex exe: {e}")))? + #[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}")) + })? + } }; let program = exe.to_string_lossy().to_string(); Ok(CommandSpec { @@ -159,7 +172,7 @@ impl ToolRuntime for ApplyPatchRuntime { attempt: &SandboxAttempt<'_>, ctx: &ToolCtx, ) -> Result { - let spec = Self::build_command_spec(req)?; + let spec = Self::build_command_spec(req, &ctx.turn.config.codex_home)?; let env = attempt .env_for(spec, None) .map_err(|err| ToolError::Codex(err.into()))?; diff --git a/codex-rs/windows-sandbox-rs/src/elevated_impl.rs b/codex-rs/windows-sandbox-rs/src/elevated_impl.rs index b3a5e9a1aa..63f3b472c5 100644 --- a/codex-rs/windows-sandbox-rs/src/elevated_impl.rs +++ b/codex-rs/windows-sandbox-rs/src/elevated_impl.rs @@ -1,27 +1,27 @@ mod windows_impl { use crate::acl::allow_null_device; - use crate::allow::compute_allow_paths; use crate::allow::AllowDenyPaths; + use crate::allow::compute_allow_paths; use crate::cap::load_or_create_cap_sids; use crate::env::ensure_non_interactive_pager; use crate::env::inherit_path_env; use crate::env::normalize_null_device_env; - use crate::helper_materialization::resolve_helper_for_launch; use crate::helper_materialization::HelperExecutable; + use crate::helper_materialization::resolve_helper_for_launch; use crate::identity::require_logon_sandbox_creds; use crate::logging::log_failure; use crate::logging::log_note; use crate::logging::log_start; use crate::logging::log_success; - use crate::policy::parse_policy; use crate::policy::SandboxPolicy; + use crate::policy::parse_policy; use crate::token::convert_string_sid_to_sid; use crate::winutil::quote_windows_arg; use crate::winutil::to_wide; use anyhow::Result; - use rand::rngs::SmallRng; use rand::Rng; use rand::SeedableRng; + use rand::rngs::SmallRng; use std::collections::HashMap; use std::ffi::c_void; use std::fs; @@ -45,11 +45,11 @@ mod windows_impl { use windows_sys::Win32::System::Pipes::PIPE_WAIT; use windows_sys::Win32::System::Threading::CreateProcessWithLogonW; use windows_sys::Win32::System::Threading::GetExitCodeProcess; - use windows_sys::Win32::System::Threading::WaitForSingleObject; use windows_sys::Win32::System::Threading::INFINITE; use windows_sys::Win32::System::Threading::LOGON_WITH_PROFILE; use windows_sys::Win32::System::Threading::PROCESS_INFORMATION; use windows_sys::Win32::System::Threading::STARTUPINFOW; + use windows_sys::Win32::System::Threading::WaitForSingleObject; /// Ensures the parent directory of a path exists before writing to it. /// Walks upward from `start` to locate the git worktree root, following gitfile redirects. @@ -515,8 +515,8 @@ pub use windows_impl::run_windows_sandbox_capture; #[cfg(not(target_os = "windows"))] mod stub { - use anyhow::bail; use anyhow::Result; + use anyhow::bail; use codex_protocol::protocol::SandboxPolicy; use std::collections::HashMap; use std::path::Path; diff --git a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs index cda0800628..37db3c59c2 100644 --- a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs +++ b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs @@ -88,6 +88,34 @@ pub(crate) fn resolve_helper_for_launch( } } +pub fn resolve_current_exe_for_launch( + codex_home: &Path, + fallback_executable: &str, +) -> PathBuf { + let source = match std::env::current_exe() { + Ok(path) => path, + Err(_) => return PathBuf::from(fallback_executable), + }; + let Some(file_name) = source.file_name() else { + return source; + }; + let destination = helper_bin_dir(codex_home).join(file_name); + match copy_from_source_if_needed(&source, &destination) { + Ok(_) => destination, + Err(err) => { + let sandbox_log_dir = crate::sandbox_dir(codex_home); + log_note( + &format!( + "helper copy failed for current executable: {err:#}; falling back to legacy path {}", + source.display() + ), + Some(&sandbox_log_dir), + ); + source + } + } +} + pub(crate) fn copy_helper_if_needed( kind: HelperExecutable, codex_home: &Path, @@ -349,3 +377,4 @@ mod tests { ); } } + diff --git a/codex-rs/windows-sandbox-rs/src/lib.rs b/codex-rs/windows-sandbox-rs/src/lib.rs index 565d589724..f3581d574d 100644 --- a/codex-rs/windows-sandbox-rs/src/lib.rs +++ b/codex-rs/windows-sandbox-rs/src/lib.rs @@ -58,6 +58,8 @@ pub use dpapi::protect as dpapi_protect; #[cfg(target_os = "windows")] pub use dpapi::unprotect as dpapi_unprotect; #[cfg(target_os = "windows")] +pub use helper_materialization::resolve_current_exe_for_launch; +#[cfg(target_os = "windows")] pub use elevated_impl::run_windows_sandbox_capture as run_windows_sandbox_capture_elevated; #[cfg(target_os = "windows")] pub use hide_users::hide_current_user_profile_dir;