From cd2e03d5404bffe57fc66faae87737c833b1b3df Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Fri, 5 Jun 2026 09:10:52 -0700 Subject: [PATCH] Mitigate Windows sandbox helper elevation heuristic --- codex-rs/core/tests/suite/windows_sandbox.rs | 9 ++++++--- codex-rs/windows-sandbox-rs/src/setup.rs | 8 ++++++-- scripts/codex_package/README.md | 2 +- scripts/codex_package/layout.py | 4 ++-- scripts/install/install.ps1 | 8 ++++---- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/codex-rs/core/tests/suite/windows_sandbox.rs b/codex-rs/core/tests/suite/windows_sandbox.rs index 74d7f6a23b..e9aa4c47dd 100644 --- a/codex-rs/core/tests/suite/windows_sandbox.rs +++ b/codex-rs/core/tests/suite/windows_sandbox.rs @@ -91,9 +91,12 @@ fn stage_windows_sandbox_helpers() -> anyhow::Result<()> { .with_context(|| format!("create resources dir {}", resources_dir.display())); } } - for helper_name in ["codex-windows-sandbox-setup", "codex-command-runner"] { - let helper = codex_utils_cargo_bin::cargo_bin(helper_name)?; - let file_name = Path::new(helper_name).with_extension("exe"); + for (cargo_bin_name, file_name) in [ + ("codex-windows-sandbox-setup", "codex-windows-sandbox-helper.exe"), + ("codex-command-runner", "codex-command-runner.exe"), + ] { + let helper = codex_utils_cargo_bin::cargo_bin(cargo_bin_name)?; + let file_name = Path::new(file_name); let destination = resources_dir.join(file_name); if let Err(err) = std::fs::copy(&helper, &destination) { // A sandbox helper can briefly remain alive after the sandboxed diff --git a/codex-rs/windows-sandbox-rs/src/setup.rs b/codex-rs/windows-sandbox-rs/src/setup.rs index 428b5ff6a1..8073c8fb60 100644 --- a/codex-rs/windows-sandbox-rs/src/setup.rs +++ b/codex-rs/windows-sandbox-rs/src/setup.rs @@ -46,7 +46,10 @@ 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"; +// Avoid "setup.exe" on disk because Windows installer detection can flag that +// filename in per-user caches and force an elevation prompt. +const SETUP_EXE_FILENAME: &str = "codex-windows-sandbox-helper.exe"; +const LEGACY_SETUP_EXE_FILENAME: &str = "codex-windows-sandbox-setup.exe"; const USERPROFILE_ROOT_EXCLUSIONS: &[&str] = &[ ".ssh", ".tsh", @@ -673,6 +676,7 @@ fn find_setup_exe() -> PathBuf { fn find_setup_exe_for_current_exe(exe: &Path) -> Option { bundled_executable_path_for_exe(exe, SETUP_EXE_FILENAME) + .or_else(|| bundled_executable_path_for_exe(exe, LEGACY_SETUP_EXE_FILENAME)) } fn report_helper_failure( @@ -1290,7 +1294,7 @@ mod tests { 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"); + let setup_exe = resources_dir.join("codex-windows-sandbox-helper.exe"); fs::write(&exe, b"codex").expect("write exe"); fs::write(&setup_exe, b"setup").expect("write setup"); diff --git a/scripts/codex_package/README.md b/scripts/codex_package/README.md index 323a3ce5ba..0eec3862f9 100644 --- a/scripts/codex_package/README.md +++ b/scripts/codex_package/README.md @@ -15,7 +15,7 @@ The builder creates a canonical Codex package directory: │ ├── bwrap # Linux only │ ├── zsh/bin/zsh # supported Unix targets only │ ├── codex-command-runner.exe # Windows only -│ └── codex-windows-sandbox-setup.exe # Windows only +│ └── codex-windows-sandbox-helper.exe # Windows only └── codex-path └── rg[.exe] ``` diff --git a/scripts/codex_package/layout.py b/scripts/codex_package/layout.py index 63598672ea..5ab2b3fe8e 100644 --- a/scripts/codex_package/layout.py +++ b/scripts/codex_package/layout.py @@ -73,7 +73,7 @@ def build_package_dir( if inputs.codex_windows_sandbox_setup_bin is not None: copy_executable( inputs.codex_windows_sandbox_setup_bin, - resources_dir / "codex-windows-sandbox-setup.exe", + resources_dir / "codex-windows-sandbox-helper.exe", is_windows=True, ) @@ -147,7 +147,7 @@ def validate_package_dir( required_files.extend( [ Path("codex-resources") / "codex-command-runner.exe", - Path("codex-resources") / "codex-windows-sandbox-setup.exe", + Path("codex-resources") / "codex-windows-sandbox-helper.exe", ] ) diff --git a/scripts/install/install.ps1 b/scripts/install/install.ps1 index 6973d482e2..9b24f8ffb8 100644 --- a/scripts/install/install.ps1 +++ b/scripts/install/install.ps1 @@ -304,7 +304,7 @@ function Test-OldStandaloneBinLayout { "rg.exe", "codex-command-runner.exe", "codex-windows-sandbox.exe", - "codex-windows-sandbox-setup.exe" + "codex-windows-sandbox-helper.exe" ) foreach ($child in Get-ChildItem -LiteralPath $VisibleBinDir -Force) { if ($child.PSIsContainer) { @@ -539,7 +539,7 @@ function Test-PackageContentsAreComplete { "bin\codex.exe", "codex-path\rg.exe", "codex-resources\codex-command-runner.exe", - "codex-resources\codex-windows-sandbox-setup.exe" + "codex-resources\codex-windows-sandbox-helper.exe" ) foreach ($name in $expectedFiles) { if (-not (Test-Path -LiteralPath (Join-Path $PackageDir $name) -PathType Leaf)) { @@ -562,7 +562,7 @@ function Test-LegacyPlatformNpmContentsAreComplete { $expectedFiles = @( "codex.exe", "codex-resources\codex-command-runner.exe", - "codex-resources\codex-windows-sandbox-setup.exe", + "codex-resources\codex-windows-sandbox-helper.exe", "codex-resources\rg.exe" ) foreach ($name in $expectedFiles) { @@ -826,7 +826,7 @@ try { $copyMap = @{ "codex/codex.exe" = "codex.exe" "codex/codex-command-runner.exe" = "codex-resources\codex-command-runner.exe" - "codex/codex-windows-sandbox-setup.exe" = "codex-resources\codex-windows-sandbox-setup.exe" + "codex/codex-windows-sandbox-setup.exe" = "codex-resources\codex-windows-sandbox-helper.exe" "path/rg.exe" = "codex-resources\rg.exe" }