mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[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.
This commit is contained in:
committed by
GitHub
Unverified
parent
4c7228e423
commit
afbb69a2fb
@@ -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,
|
||||
|
||||
@@ -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<String>,
|
||||
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<PathBuf> {
|
||||
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(())
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user