Author: Spencer Michaels (Trail of Bits)
Overview
Generate a macOS Seatbelt configuration that sandboxes the target with the minimum set of permissions necessary for it to operate normally. Uses an iterative profiling approach to create allowlist-based sandbox profiles for applications.When to Use
Use this plugin when you need a targeted way to isolate a process on macOS without using containers. This can be helpful for:Supply Chain Risk
Applications at high risk of supply chain attacks (package managers, bundlers)
Untrusted Code Execution
Trusted applications that execute potentially-untrusted third-party code (Javascript bundlers, build tools)
Blast Radius Reduction
Reducing the impact if an application is exploited
Defense in Depth
Adding isolation layers to sensitive processes
How It Works
1
Profile the Target Application
Identify the actual set of permissions required for the application to run normally.
2
Generate a Minimal Seatbelt Profile
Start from a default-deny profile.
3
Iteratively Expand Permissions
Test the application empirically to identify what calls fail with the minimal profile, and add the needed permissions until the application runs normally.
4
Create Helper Scripts if Needed
If the application has multiple subcommands that perform highly different functions (such as “serve” and “build” tasks), create separate Seatbelt configurations for each, and create a helper script to switch configurations based on how the target application is invoked.
Profiling Methodology
Step 1: Identify Application Requirements
Determine what the application needs across these resource categories:- File Operations
- Network
- Process & IPC
- System
Step 2: Start with Minimal Profile
Begin with deny-all and essential process operations:Step 3: Add File Read Access (Allowlist)
Why
file-read-data instead of file-read*?file-read*allows ALL file read operations from any pathfile-read-dataonly allows reading file contents from listed paths- Combined with
file-read-metadata(allowed broadly), this gives:- ✅ Can stat/readdir anywhere (needed for path resolution)
- ❌ Cannot read contents of files outside allowlist
Step 4: Configure Network
- No Network (Most Restrictive)
- Localhost Only
- Full Network (Least Restrictive)
Use for build tools that don’t need network access:
Step 5: Test Iteratively
1
Test Basic Execution
2
Test the Actual Application
3
Test Security Restrictions
4
Debug Failures
Common failure modes:
5
Iterate Until Working
Repeat this process iteratively until you have generated a minimally-permissioned Seatbelt file and have confirmed empirically that the application works normally.
Seatbelt Syntax Reference
Path Filters
Path Filters
Parameter Substitution
Parameter Substitution
File Operations
File Operations
Network Operations
Network Operations
Process Operations
Process Operations
Example: Generic CLI Application
Known Limitations
Installation
When NOT to Use
- Linux containers (use seccomp-bpf, AppArmor, or namespaces instead)
- Windows applications
- Applications that legitimately need broad system access
- Quick one-off scripts where sandboxing overhead isn’t justified