mirror of
https://github.com/openai/codex.git
synced 2026-10-28 18:58:46 +00:00
## Why Windows temp grants could fall back to host `TEMP`/`TMP` values and bypass read-only or denied subpaths. Sandbox permissions must match the environment passed to the child process. ## What changed - Resolve `:tmpdir` from absolute `TEMP`/`TMP` paths in the completed workload environment, preserving access modes and missing-path rules without falling back to host values. - Deduplicate Windows environment keys case-insensitively in a deterministic order so permission resolution and the child environment select the same value. - Use the resolved temp policy for elevated sandbox overrides across core execution, exec-server, and direct spawning. - Launch direct-spawn sandbox wrappers with the supplied Codex executable, materializing an inner helper only when it is that executable. ## Testing Add Windows regression coverage for temp-only writes, read-only and denied carveouts, mixed-case and duplicate environment keys, unavailable temp paths, and empty or missing write-root overrides. Exercise core execution and direct spawning, and extend exec-server RPC coverage to the elevated backend with temp values set through the environment policy. GitOrigin-RevId: 16b8bd4702cc434fd743a08c75a3e4515780bff3
59 lines
2.2 KiB
Rust
59 lines
2.2 KiB
Rust
//! Windows temp override behavior not covered by a successful child launch.
|
|
use super::*;
|
|
use codex_protocol::permissions::FileSystemAccessMode;
|
|
use codex_protocol::permissions::FileSystemPath;
|
|
use codex_protocol::permissions::FileSystemSandboxEntry;
|
|
use codex_protocol::permissions::FileSystemSpecialPath;
|
|
use codex_protocol::permissions::NetworkSandboxPolicy;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn elevated_non_write_temp_never_grants_write_access() {
|
|
let dir = tempfile::TempDir::new().unwrap();
|
|
let cwd = AbsolutePathBuf::from_absolute_path(dir.path().join("work")).unwrap();
|
|
let temp = dir.path().join("temp");
|
|
std::fs::create_dir_all(cwd.as_path()).unwrap();
|
|
std::fs::create_dir_all(&temp).unwrap();
|
|
let env = HashMap::from([("Temp".into(), temp.to_string_lossy().into_owned())]);
|
|
for access in [FileSystemAccessMode::Read, FileSystemAccessMode::Deny] {
|
|
let profile = PermissionProfile::from_runtime_permissions(
|
|
&FileSystemSandboxPolicy::restricted(vec![
|
|
FileSystemSandboxEntry::new(
|
|
FileSystemPath::Special {
|
|
value: FileSystemSpecialPath::Root,
|
|
},
|
|
FileSystemAccessMode::Read,
|
|
),
|
|
FileSystemSandboxEntry::new(
|
|
FileSystemPath::Special {
|
|
value: FileSystemSpecialPath::Tmpdir,
|
|
},
|
|
access,
|
|
),
|
|
]),
|
|
NetworkSandboxPolicy::Restricted,
|
|
);
|
|
let overrides = resolve_windows_elevated_filesystem_overrides(
|
|
SandboxType::WindowsRestrictedToken,
|
|
&profile,
|
|
&cwd,
|
|
true,
|
|
&env,
|
|
)
|
|
.unwrap();
|
|
let write_roots = overrides
|
|
.as_ref()
|
|
.and_then(|o| o.write_roots_override.as_ref());
|
|
assert!(write_roots.is_none_or(Vec::is_empty));
|
|
if access == FileSystemAccessMode::Deny {
|
|
assert_eq!(
|
|
overrides.unwrap().additional_deny_read_paths,
|
|
vec![
|
|
AbsolutePathBuf::from_absolute_path(dunce::canonicalize(&temp).unwrap())
|
|
.unwrap(),
|
|
]
|
|
);
|
|
}
|
|
}
|
|
}
|