mirror of
https://github.com/openai/codex.git
synced 2026-11-02 19:43:24 +00:00
[codex] Grant Windows sandbox access to primary runtime (#31574)
## Why Codex Desktop installs its managed primary runtime under `%USERPROFILE%\.cache\codex-runtimes`. Elevated Windows sandbox commands run as dedicated sandbox users. The synchronous runtime ACL refresh repairs read/execute access for the Desktop runtime directories under `%LOCALAPPDATA%\OpenAI\Codex`, but did not include the managed primary runtime cache. As a result, the Desktop app could discover a bundled runtime while a sandboxed command received `ACCESS_DENIED` when reading or executing it. ## What changed - Include `%USERPROFILE%\.cache\codex-runtimes` in the managed runtime paths considered by the Windows sandbox ACL refresh. - Reuse the existing inherited read/execute ACL repair; no write permission is added. - Add Windows-target regression coverage for the runtime path list and the primary-runtime-only case. ## Impact Bundled Python, Node, and native tools remain usable from elevated Windows sandbox sessions without broadening write access or granting access to the rest of the user profile. ## Validation - `just fmt` - `just test -p codex-windows-sandbox` (10/10 host-side tests passed) - Windows-target path tests included for CI
This commit is contained in:
@@ -10,20 +10,22 @@ 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;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "setup_runtime_bin_tests.rs"]
|
||||
mod tests;
|
||||
|
||||
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 = 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");
|
||||
let runtime_paths = runtime_paths(
|
||||
local_app_data_root(),
|
||||
std::env::var_os("USERPROFILE").map(PathBuf::from),
|
||||
);
|
||||
|
||||
for runtime_path in [codex_root.join("bin"), codex_root.join("runtimes")] {
|
||||
for runtime_path in runtime_paths {
|
||||
if !runtime_path.is_dir() {
|
||||
continue;
|
||||
}
|
||||
@@ -86,6 +88,20 @@ pub(super) fn ensure_codex_app_runtime_paths_readable(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn runtime_paths(local_app_data: Option<PathBuf>, user_profile: Option<PathBuf>) -> Vec<PathBuf> {
|
||||
let mut runtime_paths = Vec::new();
|
||||
if let Some(local_app_data) = local_app_data {
|
||||
let codex_root = local_app_data.join("OpenAI").join("Codex");
|
||||
runtime_paths.extend([codex_root.join("bin"), codex_root.join("runtimes")]);
|
||||
}
|
||||
// The managed primary runtime is installed outside the LocalAppData runtime roots.
|
||||
if let Some(user_profile) = user_profile {
|
||||
runtime_paths.push(user_profile.join(".cache").join("codex-runtimes"));
|
||||
}
|
||||
|
||||
runtime_paths
|
||||
}
|
||||
|
||||
fn local_app_data_root() -> Option<PathBuf> {
|
||||
std::env::var_os("LOCALAPPDATA")
|
||||
.map(PathBuf::from)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
use super::runtime_paths;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
fn runtime_paths_include_desktop_and_primary_runtime_roots() {
|
||||
let local_app_data = PathBuf::from(r"C:\Users\user\AppData\Local");
|
||||
let user_profile = PathBuf::from(r"C:\Users\user");
|
||||
|
||||
assert_eq!(
|
||||
runtime_paths(Some(local_app_data), Some(user_profile)),
|
||||
vec![
|
||||
PathBuf::from(r"C:\Users\user\AppData\Local\OpenAI\Codex\bin"),
|
||||
PathBuf::from(r"C:\Users\user\AppData\Local\OpenAI\Codex\runtimes"),
|
||||
PathBuf::from(r"C:\Users\user\.cache\codex-runtimes"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn primary_runtime_path_does_not_depend_on_local_app_data() {
|
||||
let user_profile = PathBuf::from(r"C:\Users\user");
|
||||
|
||||
assert_eq!(
|
||||
runtime_paths(/*local_app_data*/ None, Some(user_profile)),
|
||||
vec![PathBuf::from(r"C:\Users\user\.cache\codex-runtimes")]
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user