From 4394ec6460be342c96ce42bc46ee19b71a8d53b0 Mon Sep 17 00:00:00 2001 From: Dibyo Majumdar Date: Tue, 12 May 2026 19:26:18 -0700 Subject: [PATCH] Fix macOS sandbox platform allowances for document rendering --- .../sandboxing/src/seatbelt_base_policy.sbpl | 19 ++++++ codex-rs/sandboxing/src/seatbelt_tests.rs | 64 +++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/codex-rs/sandboxing/src/seatbelt_base_policy.sbpl b/codex-rs/sandboxing/src/seatbelt_base_policy.sbpl index 99f43e42e3..63f7d90199 100644 --- a/codex-rs/sandboxing/src/seatbelt_base_policy.sbpl +++ b/codex-rs/sandboxing/src/seatbelt_base_policy.sbpl @@ -55,7 +55,9 @@ (sysctl-name "hw.vectorunit") (sysctl-name "machdep.cpu.brand_string") (sysctl-name "kern.argmax") + (sysctl-name "kern.bootargs") (sysctl-name "kern.hostname") + (sysctl-name "kern.iossupportversion") (sysctl-name "kern.maxfilesperproc") (sysctl-name "kern.maxproc") (sysctl-name "kern.osproductversion") @@ -66,6 +68,8 @@ (sysctl-name "kern.secure_kernel") (sysctl-name "kern.usrstack64") (sysctl-name "kern.version") + (sysctl-name "kern.willshutdown") + (sysctl-name "security.mac.lockdown_mode_state") (sysctl-name "sysctl.proc_cputype") (sysctl-name "vm.loadavg") (sysctl-name-prefix "hw.perflevel") @@ -102,6 +106,16 @@ (global-name "com.apple.PowerManagement.control") ) +; AppKit and CoreServices can be initialized by app-bundle CLIs even when +; running in headless modes such as document conversion. +(allow mach-lookup + (global-name "com.apple.CoreServices.coreservicesd") + (global-name "com.apple.coreservices.launchservicesd") + (global-name "com.apple.hiservices-xpcservice") + (global-name "com.apple.lsd.mapdb") + (global-name "com.apple.windowserver.active") +) + ; allow openpty() (allow pseudo-tty) (allow file-read* file-write* file-ioctl (literal "/dev/ptmx")) @@ -120,3 +134,8 @@ (global-name "com.apple.cfprefsd.agent") (local-name "com.apple.cfprefsd.agent")) (allow user-preference-read) + +; LibreOffice uses a single-instance AF_UNIX pipe named OSL_PIPE_* under +; /private/tmp even for headless document conversion. +(allow system-socket (socket-domain AF_UNIX)) +(allow network-bind (prefix "/private/tmp/OSL_PIPE_")) diff --git a/codex-rs/sandboxing/src/seatbelt_tests.rs b/codex-rs/sandboxing/src/seatbelt_tests.rs index ecaea5d9af..b850c37478 100644 --- a/codex-rs/sandboxing/src/seatbelt_tests.rs +++ b/codex-rs/sandboxing/src/seatbelt_tests.rs @@ -1,5 +1,6 @@ use super::CreateSeatbeltCommandArgsParams; use super::MACOS_PATH_TO_SEATBELT_EXECUTABLE; +use super::MACOS_RESTRICTED_READ_ONLY_PLATFORM_DEFAULTS; use super::MACOS_SEATBELT_BASE_POLICY; use super::ProxyPolicyInputs; use super::UnixDomainSocketPolicy; @@ -108,6 +109,69 @@ fn base_policy_allows_node_cpu_sysctls() { ); } +#[test] +fn full_disk_read_policy_keeps_appkit_platform_ipc_allowances() { + let cwd = TempDir::new().expect("temp cwd"); + let file_system_policy = FileSystemSandboxPolicy::workspace_write( + &[], + /*exclude_tmpdir_env_var*/ false, + /*exclude_slash_tmp*/ false, + ); + assert!(file_system_policy.has_full_disk_read_access()); + assert!(!file_system_policy.include_platform_defaults()); + + let args = create_seatbelt_command_args(CreateSeatbeltCommandArgsParams { + command: vec!["/usr/bin/true".to_string()], + file_system_sandbox_policy: &file_system_policy, + network_sandbox_policy: NetworkSandboxPolicy::Restricted, + sandbox_policy_cwd: cwd.path(), + enforce_managed_network: false, + network: None, + extra_allow_unix_sockets: &[], + }); + let policy = seatbelt_policy_arg(&args); + + assert!( + policy.contains("; allow read-only file operations\n(allow file-read*)"), + "workspace-write policy should retain full-disk read access:\n{policy}" + ); + assert!( + !policy.contains(MACOS_RESTRICTED_READ_ONLY_PLATFORM_DEFAULTS), + "full-disk read policy should skip restricted read-only platform defaults:\n{policy}" + ); + + for required in [ + "(sysctl-name \"kern.bootargs\")", + "(sysctl-name \"kern.iossupportversion\")", + "(sysctl-name \"kern.willshutdown\")", + "(sysctl-name \"security.mac.lockdown_mode_state\")", + "(global-name \"com.apple.CoreServices.coreservicesd\")", + "(global-name \"com.apple.coreservices.launchservicesd\")", + "(global-name \"com.apple.hiservices-xpcservice\")", + "(global-name \"com.apple.lsd.mapdb\")", + "(global-name \"com.apple.windowserver.active\")", + "(allow system-socket (socket-domain AF_UNIX))", + "(allow network-bind (prefix \"/private/tmp/OSL_PIPE_\"))", + ] { + assert!( + policy.contains(required), + "workspace-write policy should include {required} from base policy:\n{policy}" + ); + } + + for overly_broad in [ + "(global-name \"com.apple.windowserver\")", + "(global-name \"com.apple.ViewBridgeAuxiliary\")", + "(allow network-bind (local unix-socket (subpath \"/private/tmp\")))", + "(allow network-outbound (remote unix-socket (subpath \"/private/tmp\")))", + ] { + assert!( + !policy.contains(overly_broad), + "workspace-write policy should not include overly broad allowance {overly_broad}:\n{policy}" + ); + } +} + #[test] fn base_policy_allows_kmp_registration_shm_read_create_and_unlink() { let expected = r##"(allow ipc-posix-shm-read-data