From afbb69a2fb52d7cb9b2f4fa1c50948dcb6d5a029 Mon Sep 17 00:00:00 2001 From: iceweasel-oai Date: Thu, 18 Jun 2026 11:04:30 -0700 Subject: [PATCH] [codex] Fix Windows sandbox runtime ACL refresh (#28943) ## Why Codex Desktop repairs sandbox-user read/execute access for binaries copied to `%LOCALAPPDATA%\OpenAI\Codex\bin`, but Computer Use launches its bundled Node runtime from `%LOCALAPPDATA%\OpenAI\Codex\runtimes`. On fresh Windows installations, `CodexSandboxUsers` may therefore be unable to execute the bundled Node binary. The command runner starts, but `CreateProcessAsUserW` fails with error 5 (`ACCESS_DENIED`), causing the Node REPL to exit before Computer Use can discover applications. This is a follow-up to #21564, which added the original runtime `bin` ACL repair. ## What changed - Expand the Codex Desktop runtime ACL roots from only `bin` to both `bin` and `runtimes`. - Apply the existing inherited read/execute ACL repair to each runtime directory when it exists. - Rename the setup helper to reflect that it now handles multiple runtime paths. ## Validation - `cargo fmt -- --check` - `just test -p codex-windows-sandbox` was run: 113 tests passed and five environment-dependent legacy execution tests failed because `CreateRestrictedToken` returned error 87. --- .../src/bin/setup_main/win.rs | 2 +- .../bin/setup_main/win/setup_runtime_bin.rs | 145 +++++++++--------- 2 files changed, 76 insertions(+), 71 deletions(-) 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(()) + }) }