diff --git a/codex-rs/linux-sandbox/README.md b/codex-rs/linux-sandbox/README.md index b118931623..164e316e2c 100644 --- a/codex-rs/linux-sandbox/README.md +++ b/codex-rs/linux-sandbox/README.md @@ -29,7 +29,8 @@ commands that would enter the bubblewrap path. **Current Behavior** -- Legacy `SandboxPolicy` / `sandbox_mode` configs remain supported. +- Legacy `sandbox_mode` configs remain supported and are converted to + `PermissionProfile` before sandbox execution. - Bubblewrap is the default filesystem sandbox. - If `bwrap` is present on `PATH` outside the current working directory, the helper uses it. @@ -47,9 +48,8 @@ commands that would enter the bubblewrap path. - Filesystem-restricted execution requires bubblewrap. The legacy Landlock option is rejected for these policies because it cannot isolate app-server Unix sockets. Disable `features.use_legacy_landlock` when upgrading. -- Split-only filesystem policies that do not round-trip through the legacy - `SandboxPolicy` model stay on bubblewrap so nested read-only or denied - carveouts are preserved. +- Bubblewrap preserves nested read-only and denied filesystem rules from + `PermissionProfile`. - When bubblewrap is active, the helper applies `PR_SET_NO_NEW_PRIVS` and a seccomp filter in-process after establishing the filesystem view. Restricted network policies block network syscalls; filesystem-restricted policies with diff --git a/codex-rs/memories/write/src/phase2_sandbox_tests.rs b/codex-rs/memories/write/src/phase2_sandbox_tests.rs index 8b2acc9ede..5a97472573 100644 --- a/codex-rs/memories/write/src/phase2_sandbox_tests.rs +++ b/codex-rs/memories/write/src/phase2_sandbox_tests.rs @@ -5,9 +5,9 @@ use codex_model_provider::create_model_provider; use codex_protocol::models::ManagedFileSystemPermissions; use codex_protocol::models::PermissionProfile; use codex_protocol::permissions::FileSystemPolicyProjection; +use codex_protocol::permissions::FileSystemSandboxPolicy; use codex_protocol::permissions::NetworkSandboxPolicy; use codex_protocol::protocol::AskForApproval; -use codex_protocol::protocol::SandboxPolicy; use core_test_support::responses::start_mock_server; use core_test_support::test_codex::test_codex; use pretty_assertions::assert_eq; @@ -28,12 +28,14 @@ async fn consolidation_uses_canonical_parent_enforcement() -> anyhow::Result<()> ); let root = crate::memory_root(&test.config.codex_home); - let managed_worker_policy = SandboxPolicy::WorkspaceWrite { - writable_roots: vec![root.clone()], - network_access: false, - exclude_tmpdir_env_var: true, - exclude_slash_tmp: true, - }; + let managed_worker_profile = PermissionProfile::from_runtime_permissions( + &FileSystemSandboxPolicy::workspace_write( + std::slice::from_ref(&root), + /*exclude_tmpdir_env_var*/ true, + /*exclude_slash_tmp*/ true, + ), + NetworkSandboxPolicy::Restricted, + ); for (parent_permission_profile, expected_permission_profile) in [ (PermissionProfile::Disabled, PermissionProfile::Disabled), @@ -58,10 +60,7 @@ async fn consolidation_uses_canonical_parent_enforcement() -> anyhow::Result<()> file_system: ManagedFileSystemPermissions::Unrestricted, network: NetworkSandboxPolicy::Enabled, }, - PermissionProfile::from_legacy_sandbox_policy_for_cwd( - &managed_worker_policy, - root.as_path(), - ), + managed_worker_profile, ), ] { let agent_config = diff --git a/codex-rs/memories/write/src/phase2_workspace_roots_tests.rs b/codex-rs/memories/write/src/phase2_workspace_roots_tests.rs index 7529432190..3e97277ba0 100644 --- a/codex-rs/memories/write/src/phase2_workspace_roots_tests.rs +++ b/codex-rs/memories/write/src/phase2_workspace_roots_tests.rs @@ -1,8 +1,10 @@ use super::agent; use crate::memory_root; use codex_model_provider::create_model_provider; +use codex_protocol::models::PermissionProfile; +use codex_protocol::permissions::FileSystemSandboxPolicy; +use codex_protocol::permissions::NetworkSandboxPolicy; use codex_protocol::permissions::PROTECTED_METADATA_PATH_NAMES; -use codex_protocol::protocol::SandboxPolicy; use core_test_support::responses::start_mock_server; use core_test_support::test_codex::test_codex; use pretty_assertions::assert_eq; @@ -60,13 +62,15 @@ async fn consolidation_rebinds_workspace_roots_to_memory_root() -> anyhow::Resul (&root, &vec![root.clone()], [root.clone()].as_slice(), true), ); assert_eq!( - agent_config.legacy_sandbox_policy(), - SandboxPolicy::WorkspaceWrite { - writable_roots: Vec::new(), - network_access: false, - exclude_tmpdir_env_var: true, - exclude_slash_tmp: true, - } + agent_config.permissions.permission_profile(), + &PermissionProfile::from_runtime_permissions( + &FileSystemSandboxPolicy::workspace_write( + std::slice::from_ref(&root), + /*exclude_tmpdir_env_var*/ true, + /*exclude_slash_tmp*/ true, + ), + NetworkSandboxPolicy::Restricted, + ) ); let filesystem = agent_config.permissions.file_system_sandbox_policy(); assert!(filesystem.can_write_local_path_with_cwd(root.join("memory.md").as_path(), &root)); diff --git a/codex-rs/rollout-trace/src/thread_tests.rs b/codex-rs/rollout-trace/src/thread_tests.rs index 5253d36478..28902eef9e 100644 --- a/codex-rs/rollout-trace/src/thread_tests.rs +++ b/codex-rs/rollout-trace/src/thread_tests.rs @@ -14,7 +14,6 @@ use codex_protocol::protocol::FileChange; use codex_protocol::protocol::PatchApplyBeginEvent; use codex_protocol::protocol::PatchApplyEndEvent; use codex_protocol::protocol::PatchApplyStatus; -use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SubAgentSource; use pretty_assertions::assert_eq; @@ -50,7 +49,7 @@ fn create_in_root_writes_replayable_lifecycle_events() -> anyhow::Result<()> { model: "gpt-test".to_string(), provider_name: "test-provider".to_string(), approval_policy: "never".to_string(), - sandbox_policy: format!("{:?}", SandboxPolicy::DangerFullAccess), + sandbox_policy: "DangerFullAccess".to_string(), }, )?; @@ -134,7 +133,7 @@ fn spawned_thread_start_appends_to_root_bundle() -> anyhow::Result<()> { model: "gpt-test".to_string(), provider_name: "test-provider".to_string(), approval_policy: "never".to_string(), - sandbox_policy: format!("{:?}", SandboxPolicy::DangerFullAccess), + sandbox_policy: "DangerFullAccess".to_string(), })?; child_trace.record_ended(RolloutStatus::Completed); let bundle_dir = single_bundle_dir(temp.path())?; diff --git a/codex-rs/utils/cli/src/sandbox_mode_cli_arg.rs b/codex-rs/utils/cli/src/sandbox_mode_cli_arg.rs index b7d1a248b8..0f8de913b9 100644 --- a/codex-rs/utils/cli/src/sandbox_mode_cli_arg.rs +++ b/codex-rs/utils/cli/src/sandbox_mode_cli_arg.rs @@ -1,8 +1,7 @@ //! Standard type to use with the `--sandbox` (`-s`) CLI option. //! -//! This mirrors the variants of [`codex_protocol::protocol::SandboxPolicy`], but -//! without any of the associated data so it can be expressed as a simple flag -//! on the command-line. Users that need to tweak the advanced options for +//! This mirrors [`codex_protocol::config_types::SandboxMode`] so built-in modes +//! can be expressed as a simple flag on the command line. Users that need to tweak the advanced options for //! `workspace-write` can continue to do so via `-c` overrides or their //! `config.toml`.