macOS XPC Sandbox
March 24, 2026 ยท View on GitHub
agentsh provides XPC/Mach IPC control on macOS through sandbox profiles that restrict which system services sandboxed processes can communicate with.
Overview
XPC (Cross-Process Communication) is macOS's primary IPC mechanism. By default, any process can connect to any XPC service. agentsh's XPC sandbox restricts this using Apple's sandbox profile system.
Configuration
sandbox:
xpc:
enabled: true
mode: enforce # enforce | audit | disabled
mach_services:
default_action: deny # deny (allowlist) or allow (blocklist)
allow:
- "com.apple.system.logger"
- "com.apple.CoreServices.coreservicesd"
block:
- "com.apple.security.authhost"
allow_prefixes:
- "com.apple.cfprefsd."
block_prefixes:
- "com.apple.accessibility."
How It Works
- When
agentsh execruns a command on macOS with XPC enabled, it wraps the command withagentsh-macwrap - The wrapper generates an SBPL (Sandbox Profile Language) profile with mach-lookup rules
- The sandbox is applied via
sandbox_init_with_parameters()before exec - The sandboxed process can only connect to allowed XPC services
Default Allow List
When default_action: deny, these services are allowed by default:
com.apple.system.logger- System loggingcom.apple.CoreServices.coreservicesd- Core servicescom.apple.lsd.mapdb- Launch servicescom.apple.SecurityServer- Code signingcom.apple.cfprefsd.*- Preferences
Default Block List
When default_action: allow, these are blocked by default:
com.apple.accessibility.*- Accessibility APIs (input injection)com.apple.tccd.*- TCC bypass attemptscom.apple.security.authhost- Auth dialog spoofingcom.apple.coreservices.appleevents- AppleScript
Discovering Required Services
To find which XPC services your application needs:
# Trace sandbox violations
sandbox-exec -t /tmp/trace.out -p "(version 1)(deny default)(allow mach-lookup)" ./myapp
# Watch system log
log stream --predicate 'subsystem == "com.apple.sandbox"' --level debug
Audit Events
XPC sandbox violations generate xpc_sandbox_violation events in the audit log.
Dynamic Seatbelt (Policy-Driven Profiles)
Starting with dynamic seatbelt mode, sandbox profiles are no longer generated locally by agentsh-macwrap. Instead, they are built server-side from policy YAML using the SBPL builder.
How It Works
- Server-side compilation: When a session starts, the server reads the active policy and compiles an SBPL profile using the SBPL builder. The profile encodes deny-default rules with specific allows for file paths, exec paths, Mach services, and network access derived from policy.
- Extension tokens: Runtime file access grants are issued as sandbox extension tokens. These allow the sandboxed process to access paths not in the original profile (e.g., newly created temp files or workspace expansions) without regenerating the full profile.
- Pre-compiled delivery: The compiled SBPL profile is sent to
agentsh-macwrapas part of the exec request. macwrap applies the pre-compiled profile viasandbox_init_with_parameters()instead of generating one locally. - Backwards compatibility: If
CompiledProfileis empty in the exec request, macwrap falls back to legacy local profile generation. This ensures older servers or configurations continue to work without changes.