mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat(sandbox): add Windows deny-read parity (#18202)
## Why The split filesystem policy stack already supports exact and glob `access = none` read restrictions on macOS and Linux. Windows still needed subprocess handling for those deny-read policies without claiming enforcement from a backend that cannot provide it. ## Key finding The unelevated restricted-token backend cannot safely enforce deny-read overlays. Its `WRITE_RESTRICTED` token model is authoritative for write checks, not read denials, so this PR intentionally fails that backend closed when deny-read overrides are present instead of claiming unsupported enforcement. ## What changed This PR adds the Windows deny-read enforcement layer and makes the backend split explicit: - Resolves Windows deny-read filesystem policy entries into concrete ACL targets. - Preserves exact missing paths so they can be materialized and denied before an enforceable sandboxed process starts. - Snapshot-expands existing glob matches into ACL targets for Windows subprocess enforcement. - Honors `glob_scan_max_depth` when expanding Windows deny-read globs. - Plans both the configured lexical path and the canonical target for existing paths so reparse-point aliases are covered. - Threads deny-read overrides through the elevated/logon-user Windows sandbox backend and unified exec. - Applies elevated deny-read ACLs synchronously before command launch rather than delegating them to the background read-grant helper. - Reconciles persistent deny-read ACEs per sandbox principal so policy changes do not leave stale deny-read ACLs behind. - Fails closed on the unelevated restricted-token backend when deny-read overrides are present, because its `WRITE_RESTRICTED` token model is not authoritative for read denials. ## Landed prerequisites These prerequisite PRs are already on `main`: 1. #15979 `feat(permissions): add glob deny-read policy support` 2. #18096 `feat(sandbox): add glob deny-read platform enforcement` 3. #17740 `feat(config): support managed deny-read requirements` This PR targets `main` directly and contains only the Windows deny-read enforcement layer. ## Implementation notes - Exact deny-read paths remain enforceable on the elevated path even when they do not exist yet: Windows materializes the missing path before applying the deny ACE, so the sandboxed command cannot create and read it during the same run. - Existing exact deny paths are preserved lexically until the ACL planner, which then adds the canonical target as a second ACL target when needed. That keeps both the configured alias and the resolved object covered. - Windows ACLs do not consume Codex glob syntax directly, so glob deny-read entries are expanded to the concrete matches that exist before process launch. - Glob traversal deduplicates directory visits within each pattern walk to avoid cycles, without collapsing distinct lexical roots that happen to resolve to the same target. - Persistent deny-read ACL state is keyed by sandbox principal SID, so cleanup only removes ACEs owned by the same backend principal. - Deny-read ACEs are fail-closed on the elevated path: setup aborts if mandatory deny-read ACL application fails. - Unelevated restricted-token sessions reject deny-read overrides early instead of running with a silently unenforceable read policy. ## Verification - `cargo test -p codex-core windows_restricted_token_rejects_unreadable_split_carveouts` - `just fmt` - `just fix -p codex-core` - `just fix -p codex-windows-sandbox` - GitHub Actions rerun is in progress on the pushed head. --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -2905,12 +2905,6 @@ impl Config {
|
||||
}
|
||||
})
|
||||
.map_err(std::io::Error::from)?;
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
startup_warnings.push(format!(
|
||||
"managed filesystem deny_read from {filesystem_requirements_source} is only enforced for direct file tools on Windows; shell subprocess reads are not sandboxed"
|
||||
));
|
||||
}
|
||||
}
|
||||
apply_requirement_constrained_value(
|
||||
"approvals_reviewer",
|
||||
|
||||
+53
-48
@@ -97,17 +97,19 @@ pub struct ExecParams {
|
||||
|
||||
/// Resolved filesystem overrides for the Windows sandbox backends.
|
||||
///
|
||||
/// The unelevated restricted-token backend only consumes extra deny-write
|
||||
/// carveouts on top of the legacy `WorkspaceWrite` allow set. The elevated
|
||||
/// backend can also consume explicit read and write roots during setup/refresh.
|
||||
/// Read-root overrides are layered on top of the baseline helper roots that the
|
||||
/// elevated setup path needs to launch the sandboxed command. Split policies
|
||||
/// that opt into platform defaults carry that explicitly with the override.
|
||||
/// The elevated Windows backend consumes extra deny-read paths plus explicit
|
||||
/// read and write roots during setup/refresh. The unelevated restricted-token
|
||||
/// backend only consumes extra deny-write carveouts on top of the legacy
|
||||
/// `WorkspaceWrite` allow set. Read-root overrides are layered on top of the
|
||||
/// baseline helper roots that the elevated setup path needs to launch the
|
||||
/// sandboxed command; split policies that opt into platform defaults carry
|
||||
/// that explicitly with the override.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct WindowsSandboxFilesystemOverrides {
|
||||
pub(crate) read_roots_override: Option<Vec<PathBuf>>,
|
||||
pub(crate) read_roots_include_platform_defaults: bool,
|
||||
pub(crate) write_roots_override: Option<Vec<PathBuf>>,
|
||||
pub(crate) additional_deny_read_paths: Vec<AbsolutePathBuf>,
|
||||
pub(crate) additional_deny_write_paths: Vec<AbsolutePathBuf>,
|
||||
}
|
||||
|
||||
@@ -564,7 +566,7 @@ async fn exec_windows_sandbox(
|
||||
) -> Result<RawExecToolCallOutput> {
|
||||
use crate::config::find_codex_home;
|
||||
use codex_windows_sandbox::run_windows_sandbox_capture_elevated;
|
||||
use codex_windows_sandbox::run_windows_sandbox_capture_with_extra_deny_write_paths;
|
||||
use codex_windows_sandbox::run_windows_sandbox_capture_with_filesystem_overrides;
|
||||
|
||||
let ExecParams {
|
||||
command,
|
||||
@@ -605,13 +607,10 @@ async fn exec_windows_sandbox(
|
||||
let proxy_enforced = network.is_some();
|
||||
let use_elevated = windows_sandbox_uses_elevated_backend(sandbox_level, proxy_enforced);
|
||||
let additional_deny_write_paths = windows_sandbox_filesystem_overrides
|
||||
.map(|overrides| {
|
||||
overrides
|
||||
.additional_deny_write_paths
|
||||
.iter()
|
||||
.map(AbsolutePathBuf::to_path_buf)
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.map(|overrides| overrides.additional_deny_write_paths.clone())
|
||||
.unwrap_or_default();
|
||||
let additional_deny_read_paths = windows_sandbox_filesystem_overrides
|
||||
.map(|overrides| overrides.additional_deny_read_paths.clone())
|
||||
.unwrap_or_default();
|
||||
let elevated_read_roots_override = windows_sandbox_filesystem_overrides
|
||||
.and_then(|overrides| overrides.read_roots_override.clone());
|
||||
@@ -619,15 +618,6 @@ async fn exec_windows_sandbox(
|
||||
.is_some_and(|overrides| overrides.read_roots_include_platform_defaults);
|
||||
let elevated_write_roots_override = windows_sandbox_filesystem_overrides
|
||||
.and_then(|overrides| overrides.write_roots_override.clone());
|
||||
let elevated_deny_write_paths = windows_sandbox_filesystem_overrides
|
||||
.map(|overrides| {
|
||||
overrides
|
||||
.additional_deny_write_paths
|
||||
.iter()
|
||||
.map(AbsolutePathBuf::to_path_buf)
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let spawn_res = tokio::task::spawn_blocking(move || {
|
||||
if use_elevated {
|
||||
run_windows_sandbox_capture_elevated(
|
||||
@@ -645,11 +635,12 @@ async fn exec_windows_sandbox(
|
||||
read_roots_include_platform_defaults:
|
||||
elevated_read_roots_include_platform_defaults,
|
||||
write_roots_override: elevated_write_roots_override.as_deref(),
|
||||
deny_write_paths_override: &elevated_deny_write_paths,
|
||||
deny_read_paths_override: &additional_deny_read_paths,
|
||||
deny_write_paths_override: &additional_deny_write_paths,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
run_windows_sandbox_capture_with_extra_deny_write_paths(
|
||||
run_windows_sandbox_capture_with_filesystem_overrides(
|
||||
policy_str.as_str(),
|
||||
&sandbox_cwd,
|
||||
codex_home.as_ref(),
|
||||
@@ -657,6 +648,7 @@ async fn exec_windows_sandbox(
|
||||
&cwd,
|
||||
env,
|
||||
timeout_ms,
|
||||
&additional_deny_read_paths,
|
||||
&additional_deny_write_paths,
|
||||
windows_sandbox_private_desktop,
|
||||
)
|
||||
@@ -1049,22 +1041,24 @@ pub(crate) fn resolve_windows_restricted_token_filesystem_overrides(
|
||||
));
|
||||
}
|
||||
|
||||
if !file_system_sandbox_policy.has_full_disk_read_access() {
|
||||
// The restricted-token backend can still enforce split write restrictions,
|
||||
// but its WRITE_RESTRICTED token does not make capability SID deny-read ACEs
|
||||
// participate in read access checks. Read restrictions therefore require the
|
||||
// elevated backend, even when the filesystem root remains readable.
|
||||
if !windows_policy_has_root_read_access(file_system_sandbox_policy, sandbox_policy_cwd) {
|
||||
return Err(
|
||||
"windows unelevated restricted-token sandbox cannot enforce split filesystem read restrictions directly; refusing to run unsandboxed"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
if !file_system_sandbox_policy
|
||||
.get_unreadable_roots_with_cwd(sandbox_policy_cwd)
|
||||
.is_empty()
|
||||
|| !file_system_sandbox_policy
|
||||
.get_unreadable_globs_with_cwd(sandbox_policy_cwd)
|
||||
.is_empty()
|
||||
{
|
||||
let additional_deny_read_paths = codex_windows_sandbox::resolve_windows_deny_read_paths(
|
||||
file_system_sandbox_policy,
|
||||
sandbox_policy_cwd,
|
||||
)?;
|
||||
if !additional_deny_read_paths.is_empty() {
|
||||
return Err(
|
||||
"windows unelevated restricted-token sandbox cannot enforce unreadable split filesystem carveouts directly; refusing to run unsandboxed"
|
||||
"windows unelevated restricted-token sandbox cannot enforce deny-read restrictions directly; refusing to run unsandboxed"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
@@ -1131,7 +1125,7 @@ pub(crate) fn resolve_windows_restricted_token_filesystem_overrides(
|
||||
}
|
||||
}
|
||||
|
||||
if additional_deny_write_paths.is_empty() {
|
||||
if additional_deny_read_paths.is_empty() && additional_deny_write_paths.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
@@ -1139,6 +1133,7 @@ pub(crate) fn resolve_windows_restricted_token_filesystem_overrides(
|
||||
read_roots_override: None,
|
||||
read_roots_include_platform_defaults: false,
|
||||
write_roots_override: None,
|
||||
additional_deny_read_paths,
|
||||
additional_deny_write_paths: additional_deny_write_paths
|
||||
.into_iter()
|
||||
.map(|path| AbsolutePathBuf::from_absolute_path(path).map_err(|err| err.to_string()))
|
||||
@@ -1152,6 +1147,16 @@ fn normalize_windows_override_path(path: &Path) -> std::result::Result<PathBuf,
|
||||
.map_err(|err| err.to_string())
|
||||
}
|
||||
|
||||
fn windows_policy_has_root_read_access(
|
||||
file_system_sandbox_policy: &FileSystemSandboxPolicy,
|
||||
cwd: &AbsolutePathBuf,
|
||||
) -> bool {
|
||||
let Some(root) = cwd.as_path().ancestors().last() else {
|
||||
return false;
|
||||
};
|
||||
file_system_sandbox_policy.can_read_path_with_cwd(root, cwd.as_path())
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_windows_elevated_filesystem_overrides(
|
||||
sandbox: SandboxType,
|
||||
sandbox_policy: &SandboxPolicy,
|
||||
@@ -1175,18 +1180,10 @@ pub(crate) fn resolve_windows_elevated_filesystem_overrides(
|
||||
));
|
||||
}
|
||||
|
||||
if !file_system_sandbox_policy
|
||||
.get_unreadable_roots_with_cwd(sandbox_policy_cwd)
|
||||
.is_empty()
|
||||
|| !file_system_sandbox_policy
|
||||
.get_unreadable_globs_with_cwd(sandbox_policy_cwd)
|
||||
.is_empty()
|
||||
{
|
||||
return Err(
|
||||
"windows elevated sandbox cannot enforce unreadable split filesystem carveouts directly; refusing to run unsandboxed"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
let additional_deny_read_paths = codex_windows_sandbox::resolve_windows_deny_read_paths(
|
||||
file_system_sandbox_policy,
|
||||
sandbox_policy_cwd,
|
||||
)?;
|
||||
|
||||
let split_writable_roots =
|
||||
file_system_sandbox_policy.get_writable_roots_with_cwd(sandbox_policy_cwd);
|
||||
@@ -1217,7 +1214,13 @@ pub(crate) fn resolve_windows_elevated_filesystem_overrides(
|
||||
.collect();
|
||||
let split_root_path_set: BTreeSet<PathBuf> = split_root_paths.iter().cloned().collect();
|
||||
|
||||
let read_roots_override = if file_system_sandbox_policy.has_full_disk_read_access() {
|
||||
// `has_full_disk_read_access()` is intentionally false when deny-read
|
||||
// entries exist. For Windows setup overrides, the important question is
|
||||
// whether the baseline still reads from the filesystem root and only needs
|
||||
// additional deny ACLs layered on top.
|
||||
let split_has_root_read_access =
|
||||
windows_policy_has_root_read_access(file_system_sandbox_policy, sandbox_policy_cwd);
|
||||
let read_roots_override = if split_has_root_read_access {
|
||||
None
|
||||
} else {
|
||||
Some(split_readable_roots)
|
||||
@@ -1265,6 +1268,7 @@ pub(crate) fn resolve_windows_elevated_filesystem_overrides(
|
||||
|
||||
if read_roots_override.is_none()
|
||||
&& write_roots_override.is_none()
|
||||
&& additional_deny_read_paths.is_empty()
|
||||
&& additional_deny_write_paths.is_empty()
|
||||
{
|
||||
return Ok(None);
|
||||
@@ -1275,6 +1279,7 @@ pub(crate) fn resolve_windows_elevated_filesystem_overrides(
|
||||
&& file_system_sandbox_policy.include_platform_defaults(),
|
||||
read_roots_override,
|
||||
write_roots_override,
|
||||
additional_deny_read_paths,
|
||||
additional_deny_write_paths,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -662,11 +662,63 @@ fn windows_restricted_token_supports_full_read_split_write_read_carveouts() {
|
||||
read_roots_override: None,
|
||||
read_roots_include_platform_defaults: false,
|
||||
write_roots_override: None,
|
||||
additional_deny_read_paths: vec![],
|
||||
additional_deny_write_paths: expected_deny_write_paths,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_restricted_token_rejects_unreadable_split_carveouts() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("tempdir");
|
||||
let cwd = dunce::canonicalize(temp_dir.path())
|
||||
.expect("canonicalize temp dir")
|
||||
.abs();
|
||||
let blocked = cwd.join("blocked");
|
||||
std::fs::create_dir_all(blocked.as_path()).expect("create blocked");
|
||||
let policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
};
|
||||
let file_system_policy = FileSystemSandboxPolicy::restricted(vec![
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::project_roots(
|
||||
/*subpath*/ None,
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: blocked },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::None,
|
||||
},
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
resolve_windows_restricted_token_filesystem_overrides(
|
||||
SandboxType::WindowsRestrictedToken,
|
||||
&policy,
|
||||
&file_system_policy,
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
&cwd,
|
||||
WindowsSandboxLevel::RestrictedToken,
|
||||
),
|
||||
Err(
|
||||
"windows unelevated restricted-token sandbox cannot enforce deny-read restrictions directly; refusing to run unsandboxed"
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_elevated_supports_split_restricted_read_roots() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("tempdir");
|
||||
@@ -699,6 +751,7 @@ fn windows_elevated_supports_split_restricted_read_roots() {
|
||||
read_roots_override: Some(vec![expected_docs]),
|
||||
read_roots_include_platform_defaults: false,
|
||||
write_roots_override: None,
|
||||
additional_deny_read_paths: vec![],
|
||||
additional_deny_write_paths: vec![],
|
||||
}))
|
||||
);
|
||||
@@ -753,6 +806,7 @@ fn windows_elevated_supports_split_write_read_carveouts() {
|
||||
read_roots_override: None,
|
||||
read_roots_include_platform_defaults: false,
|
||||
write_roots_override: None,
|
||||
additional_deny_read_paths: vec![],
|
||||
additional_deny_write_paths: vec![
|
||||
codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(expected_docs)
|
||||
.expect("absolute docs"),
|
||||
@@ -762,10 +816,11 @@ fn windows_elevated_supports_split_write_read_carveouts() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_elevated_rejects_unreadable_split_carveouts() {
|
||||
fn windows_elevated_supports_unreadable_split_carveouts() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("tempdir");
|
||||
let blocked = temp_dir.path().join("blocked");
|
||||
std::fs::create_dir_all(&blocked).expect("create blocked");
|
||||
let expected_blocked = dunce::canonicalize(&blocked).expect("canonical blocked");
|
||||
let policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
@@ -797,24 +852,38 @@ fn windows_elevated_rejects_unreadable_split_carveouts() {
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
unsupported_windows_restricted_token_sandbox_reason(
|
||||
resolve_windows_elevated_filesystem_overrides(
|
||||
SandboxType::WindowsRestrictedToken,
|
||||
&policy,
|
||||
&file_system_policy,
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
&temp_dir.path().abs(),
|
||||
WindowsSandboxLevel::Elevated,
|
||||
/*use_windows_elevated_backend*/ true,
|
||||
),
|
||||
Some(
|
||||
"windows elevated sandbox cannot enforce unreadable split filesystem carveouts directly; refusing to run unsandboxed"
|
||||
.to_string()
|
||||
)
|
||||
Ok(Some(WindowsSandboxFilesystemOverrides {
|
||||
read_roots_override: None,
|
||||
read_roots_include_platform_defaults: false,
|
||||
write_roots_override: None,
|
||||
additional_deny_read_paths: vec![
|
||||
codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(
|
||||
expected_blocked.clone(),
|
||||
)
|
||||
.expect("absolute blocked"),
|
||||
],
|
||||
additional_deny_write_paths: vec![
|
||||
codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(expected_blocked)
|
||||
.expect("absolute blocked"),
|
||||
],
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_elevated_rejects_unreadable_globs() {
|
||||
fn windows_elevated_supports_unreadable_globs() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("tempdir");
|
||||
let secret = temp_dir.path().join("app").join(".env");
|
||||
std::fs::create_dir_all(secret.parent().expect("parent")).expect("create parent");
|
||||
std::fs::write(&secret, "secret").expect("write secret");
|
||||
let policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
@@ -845,18 +914,24 @@ fn windows_elevated_rejects_unreadable_globs() {
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
unsupported_windows_restricted_token_sandbox_reason(
|
||||
resolve_windows_elevated_filesystem_overrides(
|
||||
SandboxType::WindowsRestrictedToken,
|
||||
&policy,
|
||||
&file_system_policy,
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
&temp_dir.path().abs(),
|
||||
WindowsSandboxLevel::Elevated,
|
||||
/*use_windows_elevated_backend*/ true,
|
||||
),
|
||||
Some(
|
||||
"windows elevated sandbox cannot enforce unreadable split filesystem carveouts directly; refusing to run unsandboxed"
|
||||
.to_string()
|
||||
)
|
||||
Ok(Some(WindowsSandboxFilesystemOverrides {
|
||||
read_roots_override: None,
|
||||
read_roots_include_platform_defaults: false,
|
||||
write_roots_override: None,
|
||||
additional_deny_read_paths: vec![
|
||||
codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(secret)
|
||||
.expect("absolute secret"),
|
||||
],
|
||||
additional_deny_write_paths: vec![],
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -875,6 +875,28 @@ impl UnifiedExecProcessManager {
|
||||
"windows sandbox: failed to resolve codex_home: {err}"
|
||||
))
|
||||
})?;
|
||||
let additional_deny_write_paths = request
|
||||
.windows_sandbox_filesystem_overrides
|
||||
.as_ref()
|
||||
.map(|overrides| overrides.additional_deny_write_paths.clone())
|
||||
.unwrap_or_default();
|
||||
let additional_deny_read_paths = request
|
||||
.windows_sandbox_filesystem_overrides
|
||||
.as_ref()
|
||||
.map(|overrides| overrides.additional_deny_read_paths.clone())
|
||||
.unwrap_or_default();
|
||||
let elevated_read_roots_override = request
|
||||
.windows_sandbox_filesystem_overrides
|
||||
.as_ref()
|
||||
.and_then(|overrides| overrides.read_roots_override.clone());
|
||||
let elevated_read_roots_include_platform_defaults = request
|
||||
.windows_sandbox_filesystem_overrides
|
||||
.as_ref()
|
||||
.is_some_and(|overrides| overrides.read_roots_include_platform_defaults);
|
||||
let elevated_write_roots_override = request
|
||||
.windows_sandbox_filesystem_overrides
|
||||
.as_ref()
|
||||
.and_then(|overrides| overrides.write_roots_override.clone());
|
||||
let spawned = match request.windows_sandbox_level {
|
||||
codex_protocol::config_types::WindowsSandboxLevel::Elevated => {
|
||||
codex_windows_sandbox::spawn_windows_sandbox_session_elevated(
|
||||
@@ -885,6 +907,11 @@ impl UnifiedExecProcessManager {
|
||||
request.cwd.as_path(),
|
||||
request.env.clone(),
|
||||
None,
|
||||
elevated_read_roots_override.as_deref(),
|
||||
elevated_read_roots_include_platform_defaults,
|
||||
elevated_write_roots_override.as_deref(),
|
||||
&additional_deny_read_paths,
|
||||
&additional_deny_write_paths,
|
||||
tty,
|
||||
tty,
|
||||
request.windows_sandbox_private_desktop,
|
||||
@@ -901,6 +928,8 @@ impl UnifiedExecProcessManager {
|
||||
request.cwd.as_path(),
|
||||
request.env.clone(),
|
||||
None,
|
||||
&additional_deny_read_paths,
|
||||
&additional_deny_write_paths,
|
||||
tty,
|
||||
tty,
|
||||
request.windows_sandbox_private_desktop,
|
||||
|
||||
Reference in New Issue
Block a user