mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat: Add additional macOS Sandbox Permissions for Launch Services, Contacts, Reminders (#14155)
Add additional macOS Sandbox Permissions levers for the following: - Launch Services - Contacts - Reminders
This commit is contained in:
committed by
Michael Bolin
Unverified
parent
8ac27b2a16
commit
889b4796fc
+19
-1
@@ -27,6 +27,19 @@
|
||||
(subpath "/System/iOSSupport/System/Library/SubFrameworks")
|
||||
(subpath "/usr/lib"))
|
||||
|
||||
; System Framework and AppKit resources
|
||||
(allow file-read* file-test-existence
|
||||
(subpath "/Library/Apple/System/Library/Frameworks")
|
||||
(subpath "/Library/Apple/System/Library/PrivateFrameworks")
|
||||
(subpath "/Library/Apple/usr/lib")
|
||||
(subpath "/System/Library/Frameworks")
|
||||
(subpath "/System/Library/PrivateFrameworks")
|
||||
(subpath "/System/Library/SubFrameworks")
|
||||
(subpath "/System/iOSSupport/System/Library/Frameworks")
|
||||
(subpath "/System/iOSSupport/System/Library/PrivateFrameworks")
|
||||
(subpath "/System/iOSSupport/System/Library/SubFrameworks")
|
||||
(subpath "/usr/lib"))
|
||||
|
||||
; Allow guarded vnodes.
|
||||
(allow system-mac-syscall (mac-policy-name "vnguard"))
|
||||
|
||||
@@ -87,6 +100,11 @@
|
||||
(allow file-read* (subpath "/etc"))
|
||||
(allow file-read* (subpath "/private/etc"))
|
||||
|
||||
(allow file-read* file-test-existence
|
||||
(literal "/System/Library/CoreServices")
|
||||
(literal "/System/Library/CoreServices/.SystemVersionPlatform.plist")
|
||||
(literal "/System/Library/CoreServices/SystemVersion.plist"))
|
||||
|
||||
; Some processes read /var metadata during startup.
|
||||
(allow file-read-metadata (subpath "/var"))
|
||||
(allow file-read-metadata (subpath "/private/var"))
|
||||
@@ -178,4 +196,4 @@
|
||||
|
||||
; App sandbox extensions
|
||||
(allow file-read* (extension "com.apple.app-sandbox.read"))
|
||||
(allow file-read* file-write* (extension "com.apple.app-sandbox.read-write"))
|
||||
(allow file-read* file-write* (extension "com.apple.app-sandbox.read-write"))
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use codex_protocol::models::MacOsAutomationPermission;
|
||||
use codex_protocol::models::MacOsContactsPermission;
|
||||
use codex_protocol::models::MacOsPreferencesPermission;
|
||||
use codex_protocol::models::MacOsSeatbeltProfileExtensions;
|
||||
|
||||
@@ -24,8 +25,14 @@ pub(crate) fn merge_macos_seatbelt_profile_extensions(
|
||||
&base.macos_automation,
|
||||
&permissions.macos_automation,
|
||||
),
|
||||
macos_launch_services: base.macos_launch_services || permissions.macos_launch_services,
|
||||
macos_accessibility: base.macos_accessibility || permissions.macos_accessibility,
|
||||
macos_calendar: base.macos_calendar || permissions.macos_calendar,
|
||||
macos_reminders: base.macos_reminders || permissions.macos_reminders,
|
||||
macos_contacts: union_macos_contacts_permission(
|
||||
&base.macos_contacts,
|
||||
&permissions.macos_contacts,
|
||||
),
|
||||
}),
|
||||
None => Some(permissions.clone()),
|
||||
}
|
||||
@@ -45,8 +52,12 @@ pub(crate) fn intersect_macos_seatbelt_profile_extensions(
|
||||
Some(MacOsSeatbeltProfileExtensions {
|
||||
macos_preferences: requested.macos_preferences.min(granted.macos_preferences),
|
||||
macos_automation,
|
||||
macos_launch_services: requested.macos_launch_services
|
||||
&& granted.macos_launch_services,
|
||||
macos_accessibility: requested.macos_accessibility && granted.macos_accessibility,
|
||||
macos_calendar: requested.macos_calendar && granted.macos_calendar,
|
||||
macos_reminders: requested.macos_reminders && granted.macos_reminders,
|
||||
macos_contacts: requested.macos_contacts.min(granted.macos_contacts),
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
@@ -68,6 +79,17 @@ fn union_macos_preferences_permission(
|
||||
}
|
||||
}
|
||||
|
||||
fn union_macos_contacts_permission(
|
||||
base: &MacOsContactsPermission,
|
||||
requested: &MacOsContactsPermission,
|
||||
) -> MacOsContactsPermission {
|
||||
if base < requested {
|
||||
requested.clone()
|
||||
} else {
|
||||
base.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Unions two automation permissions by keeping the more permissive result.
|
||||
///
|
||||
/// `All` wins over everything, `None` yields to the other side, and two bundle
|
||||
@@ -133,8 +155,10 @@ mod tests {
|
||||
use super::intersect_macos_seatbelt_profile_extensions;
|
||||
use super::merge_macos_seatbelt_profile_extensions;
|
||||
use super::union_macos_automation_permission;
|
||||
use super::union_macos_contacts_permission;
|
||||
use super::union_macos_preferences_permission;
|
||||
use codex_protocol::models::MacOsAutomationPermission;
|
||||
use codex_protocol::models::MacOsContactsPermission;
|
||||
use codex_protocol::models::MacOsPreferencesPermission;
|
||||
use codex_protocol::models::MacOsSeatbeltProfileExtensions;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -146,8 +170,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Calendar".to_string(),
|
||||
]),
|
||||
macos_launch_services: false,
|
||||
macos_accessibility: false,
|
||||
macos_calendar: false,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::ReadOnly,
|
||||
};
|
||||
let requested = MacOsSeatbeltProfileExtensions {
|
||||
macos_preferences: MacOsPreferencesPermission::ReadWrite,
|
||||
@@ -155,8 +182,11 @@ mod tests {
|
||||
"com.apple.Notes".to_string(),
|
||||
"com.apple.Calendar".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: true,
|
||||
macos_contacts: MacOsContactsPermission::ReadWrite,
|
||||
};
|
||||
|
||||
let merged =
|
||||
@@ -170,8 +200,11 @@ mod tests {
|
||||
"com.apple.Calendar".to_string(),
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: true,
|
||||
macos_contacts: MacOsContactsPermission::ReadWrite,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -219,8 +252,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: false,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
};
|
||||
let granted = MacOsSeatbeltProfileExtensions::default();
|
||||
|
||||
@@ -229,4 +265,14 @@ mod tests {
|
||||
|
||||
assert_eq!(intersected, Some(MacOsSeatbeltProfileExtensions::default()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn union_macos_contacts_permission_does_not_downgrade() {
|
||||
let base = MacOsContactsPermission::ReadWrite;
|
||||
let requested = MacOsContactsPermission::ReadOnly;
|
||||
|
||||
let merged = union_macos_contacts_permission(&base, &requested);
|
||||
|
||||
assert_eq!(merged, MacOsContactsPermission::ReadWrite);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,6 +737,8 @@ mod tests {
|
||||
#[cfg(target_os = "macos")]
|
||||
use codex_protocol::models::MacOsAutomationPermission;
|
||||
#[cfg(target_os = "macos")]
|
||||
use codex_protocol::models::MacOsContactsPermission;
|
||||
#[cfg(target_os = "macos")]
|
||||
use codex_protocol::models::MacOsPreferencesPermission;
|
||||
#[cfg(target_os = "macos")]
|
||||
use codex_protocol::models::MacOsSeatbeltProfileExtensions;
|
||||
@@ -981,8 +983,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: false,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
@@ -1013,8 +1018,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1027,8 +1035,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -1092,8 +1103,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Calendar".to_string(),
|
||||
]),
|
||||
macos_launch_services: false,
|
||||
macos_accessibility: false,
|
||||
macos_calendar: false,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
Some(&PermissionProfile {
|
||||
file_system: Some(FileSystemPermissions {
|
||||
@@ -1105,8 +1119,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
@@ -1120,8 +1137,11 @@ mod tests {
|
||||
"com.apple.Calendar".to_string(),
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
|
||||
const MACOS_SEATBELT_BASE_POLICY: &str = include_str!("seatbelt_base_policy.sbpl");
|
||||
const MACOS_SEATBELT_NETWORK_POLICY: &str = include_str!("seatbelt_network_policy.sbpl");
|
||||
const MACOS_SEATBELT_PLATFORM_DEFAULTS: &str = include_str!("seatbelt_platform_defaults.sbpl");
|
||||
const MACOS_RESTRICTED_READ_ONLY_PLATFORM_DEFAULTS: &str =
|
||||
include_str!("restricted_read_only_platform_defaults.sbpl");
|
||||
|
||||
/// When working with `sandbox-exec`, only consider `sandbox-exec` in `/usr/bin`
|
||||
/// to defend against an attacker trying to inject a malicious version on the
|
||||
@@ -529,7 +530,7 @@ pub(crate) fn create_seatbelt_command_args_for_policies_with_extensions(
|
||||
network_policy,
|
||||
];
|
||||
if include_platform_defaults {
|
||||
policy_sections.push(MACOS_SEATBELT_PLATFORM_DEFAULTS.to_string());
|
||||
policy_sections.push(MACOS_RESTRICTED_READ_ONLY_PLATFORM_DEFAULTS.to_string());
|
||||
}
|
||||
if !seatbelt_extensions.policy.is_empty() {
|
||||
policy_sections.push(seatbelt_extensions.policy.clone());
|
||||
@@ -599,6 +600,7 @@ mod tests {
|
||||
use crate::protocol::SandboxPolicy;
|
||||
use crate::seatbelt::MACOS_PATH_TO_SEATBELT_EXECUTABLE;
|
||||
use crate::seatbelt_permissions::MacOsAutomationPermission;
|
||||
use crate::seatbelt_permissions::MacOsContactsPermission;
|
||||
use crate::seatbelt_permissions::MacOsPreferencesPermission;
|
||||
use crate::seatbelt_permissions::MacOsSeatbeltProfileExtensions;
|
||||
use codex_protocol::permissions::FileSystemAccessMode;
|
||||
@@ -787,8 +789,11 @@ mod tests {
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
);
|
||||
let policy = &args[1];
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::collections::BTreeSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub use codex_protocol::models::MacOsAutomationPermission;
|
||||
pub use codex_protocol::models::MacOsContactsPermission;
|
||||
pub use codex_protocol::models::MacOsPreferencesPermission;
|
||||
pub use codex_protocol::models::MacOsSeatbeltProfileExtensions;
|
||||
|
||||
@@ -74,7 +75,7 @@ pub(crate) fn build_seatbelt_extensions(
|
||||
MacOsAutomationPermission::None => {}
|
||||
MacOsAutomationPermission::All => {
|
||||
clauses.push(
|
||||
"(allow mach-lookup\n (global-name \"com.apple.coreservices.launchservicesd\")\n (global-name \"com.apple.coreservices.appleevents\"))"
|
||||
"(allow mach-lookup\n (global-name \"com.apple.coreservices.appleevents\"))"
|
||||
.to_string(),
|
||||
);
|
||||
clauses.push("(allow appleevent-send)".to_string());
|
||||
@@ -82,7 +83,7 @@ pub(crate) fn build_seatbelt_extensions(
|
||||
MacOsAutomationPermission::BundleIds(bundle_ids) => {
|
||||
if !bundle_ids.is_empty() {
|
||||
clauses.push(
|
||||
"(allow mach-lookup\n (global-name \"com.apple.coreservices.launchservicesd\")\n (global-name \"com.apple.coreservices.appleevents\"))"
|
||||
"(allow mach-lookup\n (global-name \"com.apple.coreservices.appleevents\"))"
|
||||
.to_string(),
|
||||
);
|
||||
let destinations = bundle_ids
|
||||
@@ -95,6 +96,14 @@ pub(crate) fn build_seatbelt_extensions(
|
||||
}
|
||||
}
|
||||
|
||||
if extensions.macos_launch_services {
|
||||
clauses.push(
|
||||
"(allow mach-lookup\n (global-name \"com.apple.coreservices.launchservicesd\")\n (global-name \"com.apple.lsd.mapdb\")\n (global-name \"com.apple.coreservices.quarantine-resolver\")\n (global-name \"com.apple.lsd.modifydb\"))"
|
||||
.to_string(),
|
||||
);
|
||||
clauses.push("(allow lsopen)".to_string());
|
||||
}
|
||||
|
||||
if extensions.macos_accessibility {
|
||||
clauses.push("(allow mach-lookup (local-name \"com.apple.axserver\"))".to_string());
|
||||
}
|
||||
@@ -103,6 +112,44 @@ pub(crate) fn build_seatbelt_extensions(
|
||||
clauses.push("(allow mach-lookup (global-name \"com.apple.CalendarAgent\"))".to_string());
|
||||
}
|
||||
|
||||
if extensions.macos_reminders {
|
||||
clauses.push(
|
||||
"(allow mach-lookup\n (global-name \"com.apple.CalendarAgent\")\n (global-name \"com.apple.remindd\"))"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut dir_params = Vec::new();
|
||||
match extensions.macos_contacts {
|
||||
MacOsContactsPermission::None => {}
|
||||
MacOsContactsPermission::ReadOnly => {
|
||||
clauses.push(
|
||||
"(allow file-read* file-test-existence\n (subpath \"/System/Library/Address Book Plug-Ins\")\n (subpath (param \"ADDRESSBOOK_DIR\")))"
|
||||
.to_string(),
|
||||
);
|
||||
clauses.push(
|
||||
"(allow mach-lookup\n (global-name \"com.apple.tccd\")\n (global-name \"com.apple.tccd.system\")\n (global-name \"com.apple.contactsd.persistence\")\n (global-name \"com.apple.AddressBook.ContactsAccountsService\")\n (global-name \"com.apple.contacts.account-caching\")\n (global-name \"com.apple.accountsd.accountmanager\"))"
|
||||
.to_string(),
|
||||
);
|
||||
if let Some(addressbook_dir) = addressbook_dir() {
|
||||
dir_params.push(("ADDRESSBOOK_DIR".to_string(), addressbook_dir));
|
||||
}
|
||||
}
|
||||
MacOsContactsPermission::ReadWrite => {
|
||||
clauses.push(
|
||||
"(allow file-read* file-write*\n (subpath \"/System/Library/Address Book Plug-Ins\")\n (subpath (param \"ADDRESSBOOK_DIR\"))\n (subpath \"/var/folders\")\n (subpath \"/private/var/folders\"))"
|
||||
.to_string(),
|
||||
);
|
||||
clauses.push(
|
||||
"(allow mach-lookup\n (global-name \"com.apple.tccd\")\n (global-name \"com.apple.tccd.system\")\n (global-name \"com.apple.contactsd.persistence\")\n (global-name \"com.apple.AddressBook.ContactsAccountsService\")\n (global-name \"com.apple.contacts.account-caching\")\n (global-name \"com.apple.accountsd.accountmanager\")\n (global-name \"com.apple.securityd.xpc\"))"
|
||||
.to_string(),
|
||||
);
|
||||
if let Some(addressbook_dir) = addressbook_dir() {
|
||||
dir_params.push(("ADDRESSBOOK_DIR".to_string(), addressbook_dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if clauses.is_empty() {
|
||||
SeatbeltExtensionPolicy::default()
|
||||
} else {
|
||||
@@ -111,11 +158,15 @@ pub(crate) fn build_seatbelt_extensions(
|
||||
"; macOS permission profile extensions\n{}\n",
|
||||
clauses.join("\n")
|
||||
),
|
||||
dir_params: Vec::new(),
|
||||
dir_params,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn addressbook_dir() -> Option<PathBuf> {
|
||||
Some(dirs::home_dir()?.join("Library/Application Support/AddressBook"))
|
||||
}
|
||||
|
||||
fn normalize_bundle_ids(bundle_ids: &[String]) -> Vec<String> {
|
||||
let mut unique = BTreeSet::new();
|
||||
for bundle_id in bundle_ids {
|
||||
@@ -139,6 +190,7 @@ fn is_valid_bundle_id(bundle_id: &str) -> bool {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::MacOsAutomationPermission;
|
||||
use super::MacOsContactsPermission;
|
||||
use super::MacOsPreferencesPermission;
|
||||
use super::MacOsSeatbeltProfileExtensions;
|
||||
use super::build_seatbelt_extensions;
|
||||
@@ -173,11 +225,7 @@ mod tests {
|
||||
..Default::default()
|
||||
});
|
||||
assert!(policy.policy.contains("(allow appleevent-send)"));
|
||||
assert!(
|
||||
policy
|
||||
.policy
|
||||
.contains("com.apple.coreservices.launchservicesd")
|
||||
);
|
||||
assert!(policy.policy.contains("com.apple.coreservices.appleevents"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -202,6 +250,28 @@ mod tests {
|
||||
.contains("(appleevent-destination \"com.apple.Notes\")")
|
||||
);
|
||||
assert!(!policy.policy.contains("bad bundle"));
|
||||
assert!(policy.policy.contains("com.apple.coreservices.appleevents"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn launch_services_emit_launch_clauses() {
|
||||
let policy = build_seatbelt_extensions(&MacOsSeatbeltProfileExtensions {
|
||||
macos_launch_services: true,
|
||||
..Default::default()
|
||||
});
|
||||
assert!(
|
||||
policy
|
||||
.policy
|
||||
.contains("com.apple.coreservices.launchservicesd")
|
||||
);
|
||||
assert!(policy.policy.contains("com.apple.lsd.mapdb"));
|
||||
assert!(
|
||||
policy
|
||||
.policy
|
||||
.contains("com.apple.coreservices.quarantine-resolver")
|
||||
);
|
||||
assert!(policy.policy.contains("com.apple.lsd.modifydb"));
|
||||
assert!(policy.policy.contains("(allow lsopen)"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -215,6 +285,56 @@ mod tests {
|
||||
assert!(policy.policy.contains("com.apple.CalendarAgent"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reminders_emit_calendar_agent_and_remindd_lookups() {
|
||||
let policy = build_seatbelt_extensions(&MacOsSeatbeltProfileExtensions {
|
||||
macos_reminders: true,
|
||||
..Default::default()
|
||||
});
|
||||
assert!(policy.policy.contains("com.apple.CalendarAgent"));
|
||||
assert!(policy.policy.contains("com.apple.remindd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contacts_read_only_emit_contacts_read_clauses() {
|
||||
let policy = build_seatbelt_extensions(&MacOsSeatbeltProfileExtensions {
|
||||
macos_contacts: MacOsContactsPermission::ReadOnly,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
assert!(
|
||||
policy
|
||||
.policy
|
||||
.contains("(subpath \"/System/Library/Address Book Plug-Ins\")")
|
||||
);
|
||||
assert!(
|
||||
policy
|
||||
.policy
|
||||
.contains("(subpath (param \"ADDRESSBOOK_DIR\"))")
|
||||
);
|
||||
assert!(policy.policy.contains("com.apple.contactsd.persistence"));
|
||||
assert!(policy.policy.contains("com.apple.accountsd.accountmanager"));
|
||||
assert!(!policy.policy.contains("com.apple.securityd.xpc"));
|
||||
assert!(
|
||||
policy
|
||||
.dir_params
|
||||
.iter()
|
||||
.any(|(key, _)| key == "ADDRESSBOOK_DIR")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contacts_read_write_emit_write_clauses() {
|
||||
let policy = build_seatbelt_extensions(&MacOsSeatbeltProfileExtensions {
|
||||
macos_contacts: MacOsContactsPermission::ReadWrite,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
assert!(policy.policy.contains("(subpath \"/var/folders\")"));
|
||||
assert!(policy.policy.contains("(subpath \"/private/var/folders\")"));
|
||||
assert!(policy.policy.contains("com.apple.securityd.xpc"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_extensions_emit_preferences_read_only_policy() {
|
||||
let policy = build_seatbelt_extensions(&MacOsSeatbeltProfileExtensions::default());
|
||||
|
||||
@@ -867,6 +867,7 @@ mod tests {
|
||||
use codex_protocol::config_types::TrustLevel;
|
||||
use codex_protocol::models::FileSystemPermissions;
|
||||
use codex_protocol::models::MacOsAutomationPermission;
|
||||
use codex_protocol::models::MacOsContactsPermission;
|
||||
use codex_protocol::models::MacOsPreferencesPermission;
|
||||
use codex_protocol::models::MacOsSeatbeltProfileExtensions;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
@@ -1466,6 +1467,7 @@ permissions:
|
||||
macos_preferences: "read_write"
|
||||
macos_automation:
|
||||
- "com.apple.Notes"
|
||||
macos_launch_services: true
|
||||
macos_accessibility: true
|
||||
macos_calendar: true
|
||||
"#,
|
||||
@@ -1480,8 +1482,39 @@ permissions:
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string(),
|
||||
]),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
..Default::default()
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skill_metadata_parses_macos_reminders_permission_yaml() {
|
||||
let parsed = serde_yaml::from_str::<SkillMetadataFile>(
|
||||
r#"
|
||||
permissions:
|
||||
macos:
|
||||
macos_reminders: true
|
||||
"#,
|
||||
)
|
||||
.expect("parse reminders skill metadata");
|
||||
|
||||
assert_eq!(
|
||||
parsed.permissions,
|
||||
Some(PermissionProfile {
|
||||
macos: Some(MacOsSeatbeltProfileExtensions {
|
||||
macos_preferences: MacOsPreferencesPermission::ReadOnly,
|
||||
macos_automation: MacOsAutomationPermission::None,
|
||||
macos_launch_services: false,
|
||||
macos_accessibility: false,
|
||||
macos_calendar: false,
|
||||
macos_reminders: true,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1503,6 +1536,7 @@ permissions:
|
||||
macos_preferences: "read_write"
|
||||
macos_automation:
|
||||
- "com.apple.Notes"
|
||||
macos_launch_services: true
|
||||
macos_accessibility: true
|
||||
macos_calendar: true
|
||||
"#,
|
||||
@@ -1525,8 +1559,11 @@ permissions:
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string()
|
||||
],),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1548,6 +1585,7 @@ permissions:
|
||||
macos_preferences: "read_write"
|
||||
macos_automation:
|
||||
- "com.apple.Notes"
|
||||
macos_launch_services: true
|
||||
macos_accessibility: true
|
||||
macos_calendar: true
|
||||
"#,
|
||||
@@ -1570,8 +1608,11 @@ permissions:
|
||||
macos_automation: MacOsAutomationPermission::BundleIds(vec![
|
||||
"com.apple.Notes".to_string()
|
||||
],),
|
||||
macos_launch_services: true,
|
||||
macos_accessibility: true,
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
macos_contacts: MacOsContactsPermission::None,
|
||||
}),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -657,6 +657,7 @@ async fn prepare_escalated_exec_permission_profile_unions_turn_and_requested_mac
|
||||
PermissionProfile {
|
||||
macos: Some(MacOsSeatbeltProfileExtensions {
|
||||
macos_calendar: true,
|
||||
macos_reminders: false,
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
|
||||
Reference in New Issue
Block a user