diff --git a/codex-rs/windows-sandbox-rs/src/bin/setup_main/win.rs b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win.rs index d862f33eca..4043bda9f6 100644 --- a/codex-rs/windows-sandbox-rs/src/bin/setup_main/win.rs +++ b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win.rs @@ -22,6 +22,7 @@ use codex_windows_sandbox::install_wfp_filters; use codex_windows_sandbox::is_command_cwd_root; use codex_windows_sandbox::load_or_create_cap_sids; use codex_windows_sandbox::log_note; +use codex_windows_sandbox::materialize_setup_dependencies; use codex_windows_sandbox::path_mask_allows; use codex_windows_sandbox::sandbox_bin_dir; use codex_windows_sandbox::sandbox_dir; @@ -918,6 +919,24 @@ fn run_setup_full(payload: &Payload, log: &mut File, sbx_dir: &Path) -> Result<( if legacy_users.exists() { let _ = std::fs::remove_file(&legacy_users); } + let materialized = materialize_setup_dependencies(&payload.codex_home, Some(sbx_dir)) + .map_err(|err| { + anyhow::Error::new(SetupFailure::new( + SetupErrorCode::HelperDependencyMaterializationFailed, + format!( + "materialize sandbox helper executables into {} failed: {err:#}", + sandbox_bin_dir(&payload.codex_home).display() + ), + )) + })?; + log_line( + log, + &format!( + "materialized {} helper executable(s) into {}", + materialized.len(), + sandbox_bin_dir(&payload.codex_home).display() + ), + )?; } unsafe { diff --git a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs index 8f0b5cb83b..5a65bb6896 100644 --- a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs +++ b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs @@ -114,6 +114,44 @@ pub fn resolve_current_exe_for_launch(codex_home: &Path, fallback_executable: &s } } +pub fn materialize_setup_dependencies( + codex_home: &Path, + log_dir: Option<&Path>, +) -> Result> { + let mut materialized = Vec::new(); + + let source = std::env::current_exe().context("resolve current executable for setup copy")?; + let file_name = source.file_name().ok_or_else(|| { + anyhow!( + "current executable has no file name for setup copy: {}", + source.display() + ) + })?; + let destination = helper_bin_dir(codex_home).join(file_name); + let outcome = copy_from_source_if_needed(&source, &destination)?; + let action = match outcome { + CopyOutcome::Reused => "reused", + CopyOutcome::ReCopied => "recopied", + }; + log_note( + &format!( + "helper copy: {action} setup-helper source={} destination={}", + source.display(), + destination.display() + ), + log_dir, + ); + materialized.push(destination); + + materialized.push(copy_helper_if_needed( + HelperExecutable::CommandRunner, + codex_home, + log_dir, + )?); + + Ok(materialized) +} + pub(crate) fn copy_helper_if_needed( kind: HelperExecutable, codex_home: &Path, diff --git a/codex-rs/windows-sandbox-rs/src/lib.rs b/codex-rs/windows-sandbox-rs/src/lib.rs index 78081b5e1f..975ec691b8 100644 --- a/codex-rs/windows-sandbox-rs/src/lib.rs +++ b/codex-rs/windows-sandbox-rs/src/lib.rs @@ -131,6 +131,8 @@ pub use elevated_impl::ElevatedSandboxCaptureRequest; #[cfg(target_os = "windows")] pub use elevated_impl::run_windows_sandbox_capture as run_windows_sandbox_capture_elevated; #[cfg(target_os = "windows")] +pub use helper_materialization::materialize_setup_dependencies; +#[cfg(target_os = "windows")] pub use helper_materialization::resolve_current_exe_for_launch; #[cfg(target_os = "windows")] pub use hide_users::hide_current_user_profile_dir; diff --git a/codex-rs/windows-sandbox-rs/src/setup_error.rs b/codex-rs/windows-sandbox-rs/src/setup_error.rs index 64e618ace1..14d806b46f 100644 --- a/codex-rs/windows-sandbox-rs/src/setup_error.rs +++ b/codex-rs/windows-sandbox-rs/src/setup_error.rs @@ -62,6 +62,8 @@ pub enum SetupErrorCode { HelperFirewallRuleVerifyFailed, /// Helper failed to spawn the read-ACL helper process. HelperReadAclHelperSpawnFailed, + /// Helper failed to materialize the setup helper dependencies into `.sandbox-bin`. + HelperDependencyMaterializationFailed, /// Helper failed to lock down sandbox directories via ACLs. HelperSandboxLockFailed, /// Helper failed for an unmapped or unexpected reason. @@ -96,6 +98,9 @@ impl SetupErrorCode { } Self::HelperFirewallRuleVerifyFailed => "helper_firewall_rule_verify_failed", Self::HelperReadAclHelperSpawnFailed => "helper_read_acl_helper_spawn_failed", + Self::HelperDependencyMaterializationFailed => { + "helper_dependency_materialization_failed" + } Self::HelperSandboxLockFailed => "helper_sandbox_lock_failed", Self::HelperUnknownError => "helper_unknown_error", }