diff --git a/codex-rs/core/src/exec.rs b/codex-rs/core/src/exec.rs index fd5cd7bcdc..591e6183ea 100644 --- a/codex-rs/core/src/exec.rs +++ b/codex-rs/core/src/exec.rs @@ -38,12 +38,12 @@ use codex_protocol::protocol::Event; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ExecCommandOutputDeltaEvent; use codex_protocol::protocol::ExecOutputStream; -use codex_protocol::protocol::SandboxPolicy; use codex_sandboxing::SandboxCommand; use codex_sandboxing::SandboxManager; use codex_sandboxing::SandboxTransformRequest; use codex_sandboxing::SandboxType; use codex_sandboxing::SandboxablePreference; +use codex_sandboxing::compatibility_sandbox_policy_for_permission_profile; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_pty::DEFAULT_OUTPUT_BYTES_CAP; use codex_utils_pty::process_group::kill_child_process_group; @@ -111,6 +111,16 @@ pub(crate) struct WindowsSandboxFilesystemOverrides { pub(crate) additional_deny_write_paths: Vec, } +#[cfg_attr(not(target_os = "windows"), allow(dead_code))] +struct RawExecSandboxContext<'a> { + sandbox: SandboxType, + permission_profile: &'a PermissionProfile, + file_system_sandbox_policy: &'a FileSystemSandboxPolicy, + network_sandbox_policy: NetworkSandboxPolicy, + sandbox_policy_cwd: &'a AbsolutePathBuf, + windows_sandbox_filesystem_overrides: Option<&'a WindowsSandboxFilesystemOverrides>, +} + fn windows_sandbox_uses_elevated_backend( sandbox_level: WindowsSandboxLevel, proxy_enforced: bool, @@ -392,11 +402,10 @@ pub fn build_exec_request( exec_req.windows_sandbox_level, exec_req.network.is_some(), ); - let sandbox_policy = exec_req.compatibility_sandbox_policy(); exec_req.windows_sandbox_filesystem_overrides = if use_windows_elevated_backend { resolve_windows_elevated_filesystem_overrides( exec_req.sandbox, - &sandbox_policy, + &exec_req.permission_profile, &exec_req.file_system_sandbox_policy, exec_req.network_sandbox_policy, sandbox_cwd, @@ -405,7 +414,7 @@ pub fn build_exec_request( } else { resolve_windows_restricted_token_filesystem_overrides( exec_req.sandbox, - &sandbox_policy, + &exec_req.permission_profile, &exec_req.file_system_sandbox_policy, exec_req.network_sandbox_policy, sandbox_cwd, @@ -421,7 +430,6 @@ pub(crate) async fn execute_exec_request( stdout_stream: Option, after_spawn: Option>, ) -> Result { - let sandbox_policy = exec_request.compatibility_sandbox_policy(); let ExecRequest { command, cwd, @@ -431,11 +439,11 @@ pub(crate) async fn execute_exec_request( expiration, capture_policy, sandbox, - windows_sandbox_policy_cwd: _, + windows_sandbox_policy_cwd, windows_sandbox_level, windows_sandbox_private_desktop, - permission_profile: _, - file_system_sandbox_policy: _, + permission_profile, + file_system_sandbox_policy, network_sandbox_policy, windows_sandbox_filesystem_overrides, arg0, @@ -456,38 +464,46 @@ pub(crate) async fn execute_exec_request( }; let start = Instant::now(); - let raw_output_result = get_raw_output_result( - params, - network_sandbox_policy, - stdout_stream, - after_spawn, + let sandbox_context = RawExecSandboxContext { sandbox, - &sandbox_policy, - windows_sandbox_filesystem_overrides.as_ref(), - ) - .await; + permission_profile: &permission_profile, + file_system_sandbox_policy: &file_system_sandbox_policy, + network_sandbox_policy, + sandbox_policy_cwd: &windows_sandbox_policy_cwd, + windows_sandbox_filesystem_overrides: windows_sandbox_filesystem_overrides.as_ref(), + }; + let raw_output_result = + get_raw_output_result(params, stdout_stream, after_spawn, sandbox_context).await; let duration = start.elapsed(); finalize_exec_result(raw_output_result, sandbox, duration) } async fn get_raw_output_result( params: ExecParams, - network_sandbox_policy: NetworkSandboxPolicy, stdout_stream: Option, after_spawn: Option>, - #[cfg_attr(not(windows), allow(unused_variables))] sandbox: SandboxType, - #[cfg_attr(not(windows), allow(unused_variables))] sandbox_policy: &SandboxPolicy, - #[cfg_attr(not(windows), allow(unused_variables))] windows_sandbox_filesystem_overrides: Option< - &WindowsSandboxFilesystemOverrides, - >, + sandbox_context: RawExecSandboxContext<'_>, ) -> Result { #[cfg(target_os = "windows")] - if sandbox == SandboxType::WindowsRestrictedToken { - return exec_windows_sandbox(params, sandbox_policy, windows_sandbox_filesystem_overrides) - .await; + if sandbox_context.sandbox == SandboxType::WindowsRestrictedToken { + return exec_windows_sandbox( + params, + sandbox_context.permission_profile, + sandbox_context.file_system_sandbox_policy, + sandbox_context.network_sandbox_policy, + sandbox_context.sandbox_policy_cwd, + sandbox_context.windows_sandbox_filesystem_overrides, + ) + .await; } - exec(params, network_sandbox_policy, stdout_stream, after_spawn).await + exec( + params, + sandbox_context.network_sandbox_policy, + stdout_stream, + after_spawn, + ) + .await } #[cfg(target_os = "windows")] @@ -559,7 +575,10 @@ fn record_windows_sandbox_spawn_failure( #[cfg(target_os = "windows")] async fn exec_windows_sandbox( params: ExecParams, - sandbox_policy: &SandboxPolicy, + permission_profile: &PermissionProfile, + file_system_sandbox_policy: &FileSystemSandboxPolicy, + network_sandbox_policy: NetworkSandboxPolicy, + sandbox_policy_cwd: &AbsolutePathBuf, windows_sandbox_filesystem_overrides: Option<&WindowsSandboxFilesystemOverrides>, ) -> Result { use crate::config::find_codex_home; @@ -589,7 +608,13 @@ async fn exec_windows_sandbox( None }; - let policy_str = serde_json::to_string(sandbox_policy).map_err(|err| { + let sandbox_policy = compatibility_sandbox_policy_for_permission_profile( + permission_profile, + file_system_sandbox_policy, + network_sandbox_policy, + sandbox_policy_cwd, + ); + let policy_str = serde_json::to_string(&sandbox_policy).map_err(|err| { CodexErr::Io(io::Error::other(format!( "failed to serialize Windows sandbox policy: {err}" ))) @@ -969,21 +994,16 @@ async fn exec( #[cfg_attr(not(target_os = "windows"), allow(dead_code))] fn should_use_windows_restricted_token_sandbox( sandbox: SandboxType, - sandbox_policy: &SandboxPolicy, file_system_sandbox_policy: &FileSystemSandboxPolicy, ) -> bool { sandbox == SandboxType::WindowsRestrictedToken && file_system_sandbox_policy.kind == FileSystemSandboxKind::Restricted - && !matches!( - sandbox_policy, - SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. } - ) } #[cfg_attr(not(test), allow(dead_code))] pub(crate) fn unsupported_windows_restricted_token_sandbox_reason( sandbox: SandboxType, - sandbox_policy: &SandboxPolicy, + permission_profile: &PermissionProfile, file_system_sandbox_policy: &FileSystemSandboxPolicy, network_sandbox_policy: NetworkSandboxPolicy, sandbox_policy_cwd: &AbsolutePathBuf, @@ -992,7 +1012,7 @@ pub(crate) fn unsupported_windows_restricted_token_sandbox_reason( if windows_sandbox_level == WindowsSandboxLevel::Elevated { resolve_windows_elevated_filesystem_overrides( sandbox, - sandbox_policy, + permission_profile, file_system_sandbox_policy, network_sandbox_policy, sandbox_policy_cwd, @@ -1002,7 +1022,7 @@ pub(crate) fn unsupported_windows_restricted_token_sandbox_reason( } else { resolve_windows_restricted_token_filesystem_overrides( sandbox, - sandbox_policy, + permission_profile, file_system_sandbox_policy, network_sandbox_policy, sandbox_policy_cwd, @@ -1014,7 +1034,7 @@ pub(crate) fn unsupported_windows_restricted_token_sandbox_reason( pub(crate) fn resolve_windows_restricted_token_filesystem_overrides( sandbox: SandboxType, - sandbox_policy: &SandboxPolicy, + permission_profile: &PermissionProfile, file_system_sandbox_policy: &FileSystemSandboxPolicy, network_sandbox_policy: NetworkSandboxPolicy, sandbox_policy_cwd: &AbsolutePathBuf, @@ -1029,22 +1049,15 @@ pub(crate) fn resolve_windows_restricted_token_filesystem_overrides( let needs_direct_runtime_enforcement = file_system_sandbox_policy .needs_direct_runtime_enforcement(network_sandbox_policy, sandbox_policy_cwd); - if should_use_windows_restricted_token_sandbox( - sandbox, - sandbox_policy, - file_system_sandbox_policy, - ) && !needs_direct_runtime_enforcement + if should_use_windows_restricted_token_sandbox(sandbox, file_system_sandbox_policy) + && !needs_direct_runtime_enforcement { return Ok(None); } - if !should_use_windows_restricted_token_sandbox( - sandbox, - sandbox_policy, - file_system_sandbox_policy, - ) { + if !should_use_windows_restricted_token_sandbox(sandbox, file_system_sandbox_policy) { return Err(format!( - "windows sandbox backend cannot enforce file_system={:?}, network={network_sandbox_policy:?}, legacy_policy={sandbox_policy:?}; refusing to run unsandboxed", + "windows sandbox backend cannot enforce file_system={:?}, network={network_sandbox_policy:?}, permission_profile={permission_profile:?}; refusing to run unsandboxed", file_system_sandbox_policy.kind, )); } @@ -1069,7 +1082,14 @@ pub(crate) fn resolve_windows_restricted_token_filesystem_overrides( ); } - let legacy_writable_roots = sandbox_policy.get_writable_roots_with_cwd(sandbox_policy_cwd); + let legacy_sandbox_policy = compatibility_sandbox_policy_for_permission_profile( + permission_profile, + file_system_sandbox_policy, + network_sandbox_policy, + sandbox_policy_cwd, + ); + let legacy_writable_roots = + legacy_sandbox_policy.get_writable_roots_with_cwd(sandbox_policy_cwd); let split_writable_roots = file_system_sandbox_policy.get_writable_roots_with_cwd(sandbox_policy_cwd); let legacy_root_paths: BTreeSet = legacy_writable_roots @@ -1154,7 +1174,7 @@ fn normalize_windows_override_path(path: &Path) -> std::result::Result = legacy_writable_roots .iter() .map(|root| normalize_path(root.root.to_path_buf())) diff --git a/codex-rs/core/src/exec_tests.rs b/codex-rs/core/src/exec_tests.rs index 1519a79ec6..ac4f5fba51 100644 --- a/codex-rs/core/src/exec_tests.rs +++ b/codex-rs/core/src/exec_tests.rs @@ -378,15 +378,14 @@ async fn process_exec_tool_call_preserves_full_buffer_capture_policy() -> Result #[test] fn windows_restricted_token_skips_external_sandbox_policies() { - let policy = SandboxPolicy::ExternalSandbox { - network_access: codex_protocol::protocol::NetworkAccess::Restricted, + let permission_profile = PermissionProfile::External { + network: NetworkSandboxPolicy::Restricted, }; - let file_system_policy = FileSystemSandboxPolicy::from(&policy); + let file_system_policy = permission_profile.file_system_sandbox_policy(); assert_eq!( should_use_windows_restricted_token_sandbox( SandboxType::WindowsRestrictedToken, - &policy, &file_system_policy, ), false @@ -395,13 +394,12 @@ fn windows_restricted_token_skips_external_sandbox_policies() { #[test] fn windows_restricted_token_runs_for_legacy_restricted_policies() { - let policy = SandboxPolicy::new_read_only_policy(); - let file_system_policy = FileSystemSandboxPolicy::from(&policy); + let permission_profile = PermissionProfile::read_only(); + let file_system_policy = permission_profile.file_system_sandbox_policy(); assert_eq!( should_use_windows_restricted_token_sandbox( SandboxType::WindowsRestrictedToken, - &policy, &file_system_policy, ), true @@ -426,37 +424,38 @@ fn windows_proxy_enforcement_uses_elevated_backend() { #[test] fn windows_restricted_token_rejects_network_only_restrictions() { - let policy = SandboxPolicy::ExternalSandbox { - network_access: codex_protocol::protocol::NetworkAccess::Restricted, - }; + let permission_profile = PermissionProfile::from_runtime_permissions( + &FileSystemSandboxPolicy::unrestricted(), + NetworkSandboxPolicy::Restricted, + ); let file_system_policy = FileSystemSandboxPolicy::unrestricted(); let sandbox_policy_cwd = AbsolutePathBuf::current_dir().expect("cwd"); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &sandbox_policy_cwd, WindowsSandboxLevel::RestrictedToken, ), Some( - "windows sandbox backend cannot enforce file_system=Unrestricted, network=Restricted, legacy_policy=ExternalSandbox { network_access: Restricted }; refusing to run unsandboxed".to_string() + "windows sandbox backend cannot enforce file_system=Unrestricted, network=Restricted, permission_profile=Managed { file_system: Unrestricted, network: Restricted }; refusing to run unsandboxed".to_string() ) ); } #[test] fn windows_restricted_token_allows_legacy_restricted_policies() { - let policy = SandboxPolicy::new_read_only_policy(); - let file_system_policy = FileSystemSandboxPolicy::from(&policy); + let permission_profile = PermissionProfile::read_only(); + let file_system_policy = permission_profile.file_system_sandbox_policy(); let sandbox_policy_cwd = AbsolutePathBuf::current_dir().expect("cwd"); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &sandbox_policy_cwd, @@ -468,19 +467,19 @@ fn windows_restricted_token_allows_legacy_restricted_policies() { #[test] fn windows_restricted_token_allows_legacy_workspace_write_policies() { - let policy = SandboxPolicy::WorkspaceWrite { - writable_roots: vec![], - network_access: false, - exclude_tmpdir_env_var: true, - exclude_slash_tmp: true, - }; - let file_system_policy = FileSystemSandboxPolicy::from(&policy); + let permission_profile = PermissionProfile::workspace_write_with( + &[], + NetworkSandboxPolicy::Restricted, + /*exclude_tmpdir_env_var*/ true, + /*exclude_slash_tmp*/ true, + ); + let file_system_policy = permission_profile.file_system_sandbox_policy(); let sandbox_policy_cwd = AbsolutePathBuf::current_dir().expect("cwd"); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &sandbox_policy_cwd, @@ -498,20 +497,21 @@ fn windows_elevated_allows_split_restricted_read_policies() { ) .expect("absolute docs"); std::fs::create_dir_all(docs.as_path()).expect("create docs"); - let policy = SandboxPolicy::ReadOnly { - network_access: false, - }; let file_system_policy = FileSystemSandboxPolicy::restricted(vec![ codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Path { path: docs }, access: codex_protocol::permissions::FileSystemAccessMode::Read, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), @@ -526,12 +526,6 @@ fn windows_restricted_token_rejects_split_only_filesystem_policies() { let temp_dir = tempfile::TempDir::new().expect("tempdir"); let docs = temp_dir.path().join("docs"); std::fs::create_dir_all(&docs).expect("create docs"); - 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 { @@ -549,11 +543,15 @@ fn windows_restricted_token_rejects_split_only_filesystem_policies() { access: codex_protocol::permissions::FileSystemAccessMode::Read, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), @@ -571,12 +569,6 @@ fn windows_restricted_token_rejects_root_write_read_only_carveouts() { let temp_dir = tempfile::TempDir::new().expect("tempdir"); let docs = temp_dir.path().join("docs"); std::fs::create_dir_all(&docs).expect("create docs"); - 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 { @@ -592,11 +584,15 @@ fn windows_restricted_token_rejects_root_write_read_only_carveouts() { access: codex_protocol::permissions::FileSystemAccessMode::Read, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), @@ -617,12 +613,6 @@ fn windows_restricted_token_supports_full_read_split_write_read_carveouts() { .abs(); let docs = cwd.join("docs"); std::fs::create_dir_all(docs.as_path()).expect("create docs"); - 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 { @@ -643,6 +633,10 @@ fn windows_restricted_token_supports_full_read_split_write_read_carveouts() { access: codex_protocol::permissions::FileSystemAccessMode::Read, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); // The legacy workspace-write root already protects top-level `.codex`, so // the restricted-token overlay only needs the extra read-only docs carveout. @@ -651,7 +645,7 @@ fn windows_restricted_token_supports_full_read_split_write_read_carveouts() { assert_eq!( resolve_windows_restricted_token_filesystem_overrides( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &cwd, @@ -672,9 +666,6 @@ fn windows_elevated_supports_split_restricted_read_roots() { let docs = temp_dir.path().join("docs"); std::fs::create_dir_all(&docs).expect("create docs"); let expected_docs = dunce::canonicalize(&docs).expect("canonical docs"); - let policy = SandboxPolicy::ReadOnly { - network_access: false, - }; let file_system_policy = FileSystemSandboxPolicy::restricted(vec![ codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Path { @@ -684,11 +675,15 @@ fn windows_elevated_supports_split_restricted_read_roots() { access: codex_protocol::permissions::FileSystemAccessMode::Read, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( resolve_windows_elevated_filesystem_overrides( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), @@ -709,12 +704,6 @@ fn windows_elevated_supports_split_write_read_carveouts() { let docs = temp_dir.path().join("docs"); std::fs::create_dir_all(&docs).expect("create docs"); let expected_docs = dunce::canonicalize(&docs).expect("canonical docs"); - 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 { @@ -738,11 +727,15 @@ fn windows_elevated_supports_split_write_read_carveouts() { access: codex_protocol::permissions::FileSystemAccessMode::Read, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( resolve_windows_elevated_filesystem_overrides( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), @@ -765,12 +758,6 @@ fn windows_elevated_rejects_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 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 { @@ -794,11 +781,15 @@ fn windows_elevated_rejects_unreadable_split_carveouts() { access: codex_protocol::permissions::FileSystemAccessMode::None, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), @@ -814,12 +805,6 @@ fn windows_elevated_rejects_unreadable_split_carveouts() { #[test] fn windows_elevated_rejects_unreadable_globs() { let temp_dir = tempfile::TempDir::new().expect("tempdir"); - 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 { @@ -842,11 +827,15 @@ fn windows_elevated_rejects_unreadable_globs() { access: codex_protocol::permissions::FileSystemAccessMode::None, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), @@ -865,12 +854,6 @@ fn windows_elevated_rejects_reopened_writable_descendants() { let docs = temp_dir.path().join("docs"); let nested = docs.join("nested"); std::fs::create_dir_all(&nested).expect("create nested"); - 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 { @@ -901,11 +884,15 @@ fn windows_elevated_rejects_reopened_writable_descendants() { access: codex_protocol::permissions::FileSystemAccessMode::Write, }, ]); + let permission_profile = PermissionProfile::from_runtime_permissions( + &file_system_policy, + NetworkSandboxPolicy::Restricted, + ); assert_eq!( unsupported_windows_restricted_token_sandbox_reason( SandboxType::WindowsRestrictedToken, - &policy, + &permission_profile, &file_system_policy, NetworkSandboxPolicy::Restricted, &temp_dir.path().abs(), diff --git a/codex-rs/core/src/sandboxing/mod.rs b/codex-rs/core/src/sandboxing/mod.rs index 5070d8da3a..cd002ffb50 100644 --- a/codex-rs/core/src/sandboxing/mod.rs +++ b/codex-rs/core/src/sandboxing/mod.rs @@ -22,9 +22,11 @@ use codex_protocol::models::PermissionProfile; pub use codex_protocol::models::SandboxPermissions; use codex_protocol::permissions::FileSystemSandboxPolicy; use codex_protocol::permissions::NetworkSandboxPolicy; +#[cfg(target_os = "windows")] use codex_protocol::protocol::SandboxPolicy; use codex_sandboxing::SandboxExecRequest; use codex_sandboxing::SandboxType; +#[cfg(target_os = "windows")] use codex_sandboxing::compatibility_sandbox_policy_for_permission_profile; use codex_utils_absolute_path::AbsolutePathBuf; use std::collections::HashMap; @@ -99,7 +101,8 @@ impl ExecRequest { } } - pub(crate) fn compatibility_sandbox_policy(&self) -> SandboxPolicy { + #[cfg(target_os = "windows")] + pub(crate) fn windows_compatibility_sandbox_policy(&self) -> SandboxPolicy { compatibility_sandbox_policy_for_permission_profile( &self.permission_profile, &self.file_system_sandbox_policy, diff --git a/codex-rs/core/src/unified_exec/process_manager.rs b/codex-rs/core/src/unified_exec/process_manager.rs index c67abc48d6..f9780fa870 100644 --- a/codex-rs/core/src/unified_exec/process_manager.rs +++ b/codex-rs/core/src/unified_exec/process_manager.rs @@ -877,7 +877,7 @@ impl UnifiedExecProcessManager { #[cfg(target_os = "windows")] if request.sandbox == codex_sandboxing::SandboxType::WindowsRestrictedToken { - let sandbox_policy = request.compatibility_sandbox_policy(); + let sandbox_policy = request.windows_compatibility_sandbox_policy(); let policy_json = serde_json::to_string(&sandbox_policy).map_err(|err| { UnifiedExecError::create_process(format!( "failed to serialize Windows sandbox policy: {err}"