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 e3376f405..e1146987b 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 @@ -819,7 +819,7 @@ fn run_setup_full(payload: &Payload, log: &mut dyn Write, sbx_dir: &Path) -> Res } if refresh_only { - setup_runtime_bin::ensure_codex_app_runtime_bin_readable( + setup_runtime_bin::ensure_codex_app_runtime_paths_readable( sandbox_group_psid, &mut refresh_errors, log, diff --git a/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs index 47cacf72e..509670e36 100644 --- a/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs +++ b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs @@ -10,83 +10,88 @@ use windows_sys::Win32::Security::OBJECT_INHERIT_ACE; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_EXECUTE; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_READ; -pub(super) fn ensure_codex_app_runtime_bin_readable( +pub(super) fn ensure_codex_app_runtime_paths_readable( sandbox_group_psid: *mut c_void, refresh_errors: &mut Vec, log: &mut dyn Write, ) -> Result<()> { - let local_app_data = std::env::var_os("LOCALAPPDATA") + let local_app_data = local_app_data_root(); + let Some(local_app_data) = local_app_data else { + return Ok(()); + }; + + let read_execute_mask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE; + let codex_root = local_app_data.join("OpenAI").join("Codex"); + + for runtime_path in [codex_root.join("bin"), codex_root.join("runtimes")] { + if !runtime_path.is_dir() { + continue; + } + + let has_access = match path_mask_allows( + &runtime_path, + &[sandbox_group_psid], + read_execute_mask, + /*require_all_bits*/ true, + ) { + Ok(has_access) => has_access, + Err(err) => { + refresh_errors.push(format!( + "runtime read/execute mask check failed on {} for sandbox_group: {err}", + runtime_path.display() + )); + super::log_line( + log, + &format!( + "runtime read/execute mask check failed on {} for sandbox_group: {err}; continuing", + runtime_path.display() + ), + )?; + false + } + }; + if has_access { + continue; + } + + super::log_line( + log, + &format!( + "granting read/execute ACE to {} for sandbox users", + runtime_path.display() + ), + )?; + let result = unsafe { + ensure_allow_mask_aces_with_inheritance( + &runtime_path, + &[sandbox_group_psid], + read_execute_mask, + OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, + ) + }; + if let Err(err) = result { + refresh_errors.push(format!( + "grant read/execute ACE failed on {} for sandbox_group: {err}", + runtime_path.display() + )); + super::log_line( + log, + &format!( + "grant read/execute ACE failed on {} for sandbox_group: {err}", + runtime_path.display() + ), + )?; + } + } + Ok(()) +} + +fn local_app_data_root() -> Option { + std::env::var_os("LOCALAPPDATA") .map(PathBuf::from) .or_else(|| { std::env::var_os("USERPROFILE") .map(PathBuf::from) .map(|profile| profile.join("AppData").join("Local")) - }); - let Some(local_app_data) = local_app_data else { - return Ok(()); - }; - - // Codex desktop copies bundled Windows binaries out of WindowsApps to this - // fixed LocalAppData cache before launching codex.exe. - let runtime_bin_dir = local_app_data.join("OpenAI").join("Codex").join("bin"); - if !runtime_bin_dir.is_dir() { - return Ok(()); - } - - let read_execute_mask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE; - let has_access = match path_mask_allows( - &runtime_bin_dir, - &[sandbox_group_psid], - read_execute_mask, - /*require_all_bits*/ true, - ) { - Ok(has_access) => has_access, - Err(err) => { - refresh_errors.push(format!( - "runtime bin read/execute mask check failed on {} for sandbox_group: {err}", - runtime_bin_dir.display() - )); - super::log_line( - log, - &format!( - "runtime bin read/execute mask check failed on {} for sandbox_group: {err}; continuing", - runtime_bin_dir.display() - ), - )?; - false - } - }; - if has_access { - return Ok(()); - } - - super::log_line( - log, - &format!( - "granting read/execute ACE to {} for sandbox users", - runtime_bin_dir.display() - ), - )?; - let result = unsafe { - ensure_allow_mask_aces_with_inheritance( - &runtime_bin_dir, - &[sandbox_group_psid], - read_execute_mask, - OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, - ) - }; - if let Err(err) = result { - refresh_errors.push(format!( - "grant read/execute ACE failed on {} for sandbox_group: {err}", - runtime_bin_dir.display() - )); - super::log_line( - log, - &format!( - "grant read/execute ACE failed on {} for sandbox_group: {err}", - runtime_bin_dir.display() - ), - )?; - } - Ok(()) + }) }