seatbelt-sandboxer by trailofbits/skills
npx skills add https://github.com/trailofbits/skills --skill seatbelt-sandboxer为应用程序生成基于最小权限允许列表的 Seatbelt 沙盒配置。
确定应用程序在以下资源类别中的需求:
| 类别 | 操作 | 常见用例 |
|---|---|---|
| 文件读取 | file-read-data, file-read-metadata, file-read-xattr, file-test-existence, |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
file-map-executable| 读取源文件、配置文件、库文件 |
| 文件写入 | file-write-data, file-write-create, file-write-unlink, file-write-mode, file-write-xattr, file-clone, file-link | 输出文件、缓存文件、临时文件 |
| 网络 | network-bind, network-inbound, network-outbound | 服务器、API 调用、包下载 |
| 进程 | process-fork, process-exec, process-exec-interpreter, process-info*, process-codesigning* | 生成子进程、脚本 |
| Mach IPC | mach-lookup, mach-register, mach-bootstrap, mach-task-name | 系统服务、XPC、通知 |
| POSIX IPC | ipc-posix-shm*, ipc-posix-sem* | 共享内存、信号量 |
| Sysctl | sysctl-read, sysctl-write | 读取系统信息(CPU、内存) |
| IOKit | iokit-open, iokit-get-properties, iokit-set-properties | 硬件访问、设备驱动程序 |
| 信号 | signal | 进程间信号处理 |
| 伪终端 | pseudo-tty | 终端模拟 |
| 系统 | system-fsctl, system-socket, system-audit, system-info | 低级系统调用 |
| 用户偏好 | user-preference-read, user-preference-write | 读取/写入用户默认设置 |
| 通知 | darwin-notification-post, distributed-notification-post | 系统通知 |
| AppleEvents | appleevent-send | 应用程序间通信(AppleScript) |
| 摄像头/麦克风 | device-camera, device-microphone | 媒体捕获 |
| 动态代码 | dynamic-code-generation | JIT 编译 |
| NVRAM | nvram-get, nvram-set, nvram-delete | 固件变量 |
对于每个类别,确定:是否需要? 以及 具体范围(路径、服务等)
如果应用程序有多个执行显著不同操作的子命令,例如像 Webpack 这样的 Javascript 打包器的 build 和 serve 命令,请执行以下操作:
从拒绝所有和基本进程操作开始,保存到具有 .sb 扩展名的合适命名的 Seatbelt 配置文件中。
(version 1)
(deny default)
;; 任何进程必需
(allow process-exec*)
(allow process-fork)
(allow sysctl-read)
;; 元数据访问(stat, readdir)- 不暴露文件内容
(allow file-read-metadata)
使用 file-read-data(而非 file-read*)进行基于允许列表的读取:
(allow file-read-data
;; 系统路径(大多数运行时必需)
(subpath "/usr")
(subpath "/bin")
(subpath "/sbin")
(subpath "/System")
(subpath "/Library")
(subpath "/opt") ;; Homebrew
(subpath "/private/var")
(subpath "/private/etc")
(subpath "/private/tmp")
(subpath "/dev")
;; 用于路径解析的根符号链接
(literal "/")
(literal "/var")
(literal "/etc")
(literal "/tmp")
(literal "/private")
;; 应用程序特定配置(根据需要自定义)
(regex (string-append "^" (regex-quote (param "HOME")) "/\\.myapp(/.*)?$"))
;; 工作目录
(subpath (param "WORKING_DIR")))
为什么使用 file-read-data 而不是 file-read*?
file-read* 允许来自任何路径的所有文件读取操作file-read-data 仅允许从列出的路径读取文件内容file-read-metadata,这提供了:
(allow file-write*
;; 仅工作目录
(subpath (param "WORKING_DIR"))
;; 临时目录
(subpath "/private/tmp")
(subpath "/tmp")
(subpath "/private/var/folders")
;; 用于输出的设备文件
(literal "/dev/null")
(literal "/dev/tty"))
三个级别的网络访问权限:
;; 选项 1:阻止所有网络(最严格 - 用于构建工具)
(deny network*)
;; 选项 2:仅限本地主机(用于开发服务器、本地服务)
;; 绑定到本地端口
(allow network-bind (local tcp "*:*"))
;; 接受入站连接
(allow network-inbound (local tcp "*:*"))
;; 仅限出站到 localhost + DNS
(allow network-outbound
(literal "/private/var/run/mDNSResponder") ;; DNS 解析
(remote ip "localhost:*")) ;; 仅限 localhost
;; 选项 3:允许所有网络(最不严格 - 尽可能避免)
(allow network*)
网络过滤器语法:
(local tcp "*:*") - 任何本地 TCP 端口(local tcp "*:8080") - 特定本地端口(remote ip "localhost:*") - 仅出站到 localhost(remote tcp) - 出站 TCP 到任何主机(literal "/private/var/run/mDNSResponder") - 用于 DNS 的 Unix 套接字生成或编辑 Seatbelt 配置文件后,在沙盒中测试目标应用程序的功能。如果有任何功能无法正常工作,请修改 Seatbelt 配置文件。重复此迭代过程,直到生成一个最小权限的 Seatbelt 文件,并经验证确认应用程序在使用您生成的 Seatbelt 配置文件进行沙盒化时能正常工作。
如果程序需要外部输入才能完全运行(例如需要应用程序进行打包的 Javascript 打包器),请从知名的、最好是官方的来源找到示例输入。例如,Rspack 打包器的这些示例项目:https://github.com/rstackjs/rstack-examples/tree/main/rspack/
# 测试基本执行
sandbox-exec -f profile.sb -D WORKING_DIR=/path -D HOME=$HOME /bin/echo "test"
# 测试实际应用程序
sandbox-exec -f profile.sb -D WORKING_DIR=/path -D HOME=$HOME \
/path/to/application --args
# 测试安全限制
sandbox-exec -f profile.sb -D WORKING_DIR=/tmp -D HOME=$HOME \
cat ~/.ssh/id_rsa
# 预期:Operation not permitted
常见故障模式:
| 症状 | 原因 | 修复方法 |
|---|---|---|
| 退出代码 134 (SIGABRT) | 沙盒违规 | 检查哪个操作被阻止 |
| 退出代码 65 + 语法错误 | 配置文件语法无效 | 检查 Seatbelt 语法 |
现有文件出现 ENOENT | 缺少 file-read-metadata | 添加 (allow file-read-metadata) |
| 进程挂起 | 缺少 IPC 权限 | 如果需要,添加 (allow mach-lookup) |
(subpath "/path") ;; /path 及其所有后代
(literal "/path/file") ;; 仅精确路径
(regex "^/path/.*\\.js$") ;; 正则表达式匹配
(param "WORKING_DIR") ;; 直接使用
(subpath (param "WORKING_DIR")) ;; 在 subpath 中
(string-append (param "HOME") "/.config") ;; 连接
(regex-quote (param "HOME")) ;; 转义用于正则表达式
文件操作:
(allow file-read-data ...) ;; 读取文件内容
(allow file-read-metadata) ;; stat, lstat, readdir(无内容)
(allow file-read-xattr ...) ;; 读取扩展属性
(allow file-test-existence ...) ;; 检查文件是否存在
(allow file-map-executable ...) ;; mmap 可执行文件(dylibs)
(allow file-write-data ...) ;; 写入现有文件
(allow file-write-create ...) ;; 创建新文件
(allow file-write-unlink ...) ;; 删除文件
(allow file-write* ...) ;; 所有写入操作
(allow file-read* ...) ;; 所有读取操作(谨慎使用)
进程操作:
(allow process-exec* ...) ;; 执行二进制文件
(allow process-fork) ;; 派生子进程
(allow process-info-pidinfo) ;; 查询进程信息
(allow signal) ;; 发送/接收信号
网络操作:
(allow network-bind (local tcp "*:*")) ;; 绑定到任何本地 TCP 端口
(allow network-bind (local tcp "*:8080")) ;; 绑定到特定端口
(allow network-inbound (local tcp "*:*")) ;; 接受 TCP 连接
(allow network-outbound (remote ip "localhost:*")) ;; 仅出站到 localhost
(allow network-outbound (remote tcp)) ;; 出站 TCP 到任何主机
(allow network-outbound
(literal "/private/var/run/mDNSResponder")) ;; 通过 Unix 套接字的 DNS
(allow network*) ;; 所有网络(谨慎使用)
(deny network*) ;; 阻止所有网络
IPC 操作:
(allow mach-lookup ...) ;; Mach IPC 查找
(allow mach-register ...) ;; 注册 Mach 服务
(allow ipc-posix-shm* ...) ;; POSIX 共享内存
(allow ipc-posix-sem* ...) ;; POSIX 信号量
系统操作:
(allow sysctl-read) ;; 读取系统信息
(allow sysctl-write ...) ;; 修改 sysctl(罕见)
(allow iokit-open ...) ;; IOKit 设备访问
(allow pseudo-tty) ;; 终端模拟
(allow dynamic-code-generation) ;; JIT 编译
(allow user-preference-read ...) ;; 读取用户默认设置
/tmp 和 /var/folders(version 1)
(deny default)
;; 进程
(allow process-exec*)
(allow process-fork)
(allow sysctl-read)
;; 文件元数据(路径解析)
(allow file-read-metadata)
;; 文件读取(允许列表)
(allow file-read-data
(literal "/") (literal "/var") (literal "/etc") (literal "/tmp") (literal "/private")
(subpath "/usr") (subpath "/bin") (subpath "/sbin") (subpath "/opt")
(subpath "/System") (subpath "/Library") (subpath "/dev")
(subpath "/private/var") (subpath "/private/etc") (subpath "/private/tmp")
(subpath (param "WORKING_DIR")))
;; 文件写入(受限)
(allow file-write*
(subpath (param "WORKING_DIR"))
(subpath "/private/tmp") (subpath "/tmp") (subpath "/private/var/folders")
(literal "/dev/null") (literal "/dev/tty"))
;; 网络禁用
(deny network*)
用法:
sandbox-exec -f profile.sb \
-D WORKING_DIR=/path/to/project \
-D HOME=$HOME \
/path/to/application
每周安装次数
556
代码仓库
GitHub 星标数
3.9K
首次出现
2026年2月26日
安全审计
安装于
codex504
cursor503
github-copilot502
opencode502
gemini-cli501
kimi-cli500
Generate minimally-permissioned allowlist-based Seatbelt sandbox configurations for applications.
Determine what the application needs across these resource categories:
| Category | Operations | Common Use Cases |
|---|---|---|
| File Read | file-read-data, file-read-metadata, file-read-xattr, file-test-existence, file-map-executable | Reading source files, configs, libraries |
| File Write | file-write-data, file-write-create, file-write-unlink, file-write-mode, file-write-xattr, file-clone, file-link | Output files, caches, temp files |
| Network | network-bind, network-inbound, network-outbound | Servers, API calls, package downloads |
| Process | process-fork, process-exec, process-exec-interpreter, process-info*, process-codesigning* | Spawning child processes, scripts |
| Mach IPC | mach-lookup, mach-register, mach-bootstrap, mach-task-name | System services, XPC, notifications |
| POSIX IPC | ipc-posix-shm*, ipc-posix-sem* | Shared memory, semaphores |
| Sysctl | sysctl-read, sysctl-write | Reading system info (CPU, memory) |
| IOKit | iokit-open, iokit-get-properties, iokit-set-properties | Hardware access, device drivers |
| Signals | signal | Signal handling between processes |
| Pseudo-TTY | pseudo-tty | Terminal emulation |
| System | system-fsctl, system-socket, system-audit, system-info | Low-level system calls |
| User Prefs | user-preference-read, user-preference-write | Reading/writing user defaults |
| Notifications | darwin-notification-post, distributed-notification-post | System notifications |
| AppleEvents | appleevent-send | Inter-app communication (AppleScript) |
| Camera/Mic | device-camera, device-microphone | Media capture |
| Dynamic Code | dynamic-code-generation | JIT compilation |
| NVRAM | nvram-get, nvram-set, nvram-delete | Firmware variables |
For each category, determine: Needed? and Specific scope (paths, services, etc.)
If the application has multiple subcommands that perform significantly different operations, such as build and serve commands for a Javascript bundler like Webpack, do the following:
Begin with deny-all and essential process operations, saved in a suitably-named Seatbelt profile file with the .sb extension.
(version 1)
(deny default)
;; Essential for any process
(allow process-exec*)
(allow process-fork)
(allow sysctl-read)
;; Metadata access (stat, readdir) - doesn't expose file contents
(allow file-read-metadata)
Use file-read-data (not file-read*) for allowlist-based reads:
(allow file-read-data
;; System paths (required for most runtimes)
(subpath "/usr")
(subpath "/bin")
(subpath "/sbin")
(subpath "/System")
(subpath "/Library")
(subpath "/opt") ;; Homebrew
(subpath "/private/var")
(subpath "/private/etc")
(subpath "/private/tmp")
(subpath "/dev")
;; Root symlinks for path resolution
(literal "/")
(literal "/var")
(literal "/etc")
(literal "/tmp")
(literal "/private")
;; Application-specific config (customize as needed)
(regex (string-append "^" (regex-quote (param "HOME")) "/\\.myapp(/.*)?$"))
;; Working directory
(subpath (param "WORKING_DIR")))
Whyfile-read-data instead of file-read*?
file-read* allows ALL file read operations including from any pathfile-read-data only allows reading file contents from listed pathsfile-read-metadata (allowed broadly), this gives:
(allow file-write*
;; Working directory only
(subpath (param "WORKING_DIR"))
;; Temp directories
(subpath "/private/tmp")
(subpath "/tmp")
(subpath "/private/var/folders")
;; Device files for output
(literal "/dev/null")
(literal "/dev/tty"))
Three levels of network access:
;; OPTION 1: Block all network (most restrictive - use for build tools)
(deny network*)
;; OPTION 2: Localhost only (use for dev servers, local services)
;; Bind to local ports
(allow network-bind (local tcp "*:*"))
;; Accept inbound connections
(allow network-inbound (local tcp "*:*"))
;; Outbound to localhost + DNS only
(allow network-outbound
(literal "/private/var/run/mDNSResponder") ;; DNS resolution
(remote ip "localhost:*")) ;; localhost only
;; OPTION 3: Allow all network (least restrictive - avoid if possible)
(allow network*)
Network filter syntax:
(local tcp "*:*") - any local TCP port(local tcp "*:8080") - specific local port(remote ip "localhost:*") - outbound to localhost only(remote tcp) - outbound TCP to any host(literal "/private/var/run/mDNSResponder") - Unix socket for DNSAfter you generate or edit the Seatbelt profile, test the functionality of the target application in the sandbox. If anything fails to work, revise the Seatbelt profile. Repeat this process iteratively until you have generated a minimally-permissioned Seatbelt file and have confirmed empirically that the application works normally when sandboxed using the Seatbelt profile you generated.
If the program requires external input to function fully (such as a Javascript bundler that needs an application to bundle), find sample inputs from well-known, ideally official sources. For instance, these example projects for the Rspack bundler: https://github.com/rstackjs/rstack-examples/tree/main/rspack/
# Test basic execution
sandbox-exec -f profile.sb -D WORKING_DIR=/path -D HOME=$HOME /bin/echo "test"
# Test the actual application
sandbox-exec -f profile.sb -D WORKING_DIR=/path -D HOME=$HOME \
/path/to/application --args
# Test security restrictions
sandbox-exec -f profile.sb -D WORKING_DIR=/tmp -D HOME=$HOME \
cat ~/.ssh/id_rsa
# Expected: Operation not permitted
Common failure modes:
| Symptom | Cause | Fix |
|---|---|---|
| Exit code 134 (SIGABRT) | Sandbox violation | Check which operation is blocked |
| Exit code 65 + syntax error | Invalid profile syntax | Check Seatbelt syntax |
ENOENT for existing files | Missing file-read-metadata | Add (allow file-read-metadata) |
| Process hangs | Missing IPC permissions | Add (allow mach-lookup) if needed |
(subpath "/path") ;; /path and all descendants
(literal "/path/file") ;; Exact path only
(regex "^/path/.*\\.js$") ;; Regex match
(param "WORKING_DIR") ;; Direct use
(subpath (param "WORKING_DIR")) ;; In subpath
(string-append (param "HOME") "/.config") ;; Concatenation
(regex-quote (param "HOME")) ;; Escape for regex
File operations:
(allow file-read-data ...) ;; Read file contents
(allow file-read-metadata) ;; stat, lstat, readdir (no contents)
(allow file-read-xattr ...) ;; Read extended attributes
(allow file-test-existence ...) ;; Check if file exists
(allow file-map-executable ...) ;; mmap executable (dylibs)
(allow file-write-data ...) ;; Write to existing files
(allow file-write-create ...) ;; Create new files
(allow file-write-unlink ...) ;; Delete files
(allow file-write* ...) ;; All write operations
(allow file-read* ...) ;; All read operations (use sparingly)
Process operations:
(allow process-exec* ...) ;; Execute binaries
(allow process-fork) ;; Fork child processes
(allow process-info-pidinfo) ;; Query process info
(allow signal) ;; Send/receive signals
Network operations:
(allow network-bind (local tcp "*:*")) ;; Bind to any local TCP port
(allow network-bind (local tcp "*:8080")) ;; Bind to specific port
(allow network-inbound (local tcp "*:*")) ;; Accept TCP connections
(allow network-outbound (remote ip "localhost:*")) ;; Outbound to localhost only
(allow network-outbound (remote tcp)) ;; Outbound TCP to any host
(allow network-outbound
(literal "/private/var/run/mDNSResponder")) ;; DNS via Unix socket
(allow network*) ;; All network (use sparingly)
(deny network*) ;; Block all network
IPC operations:
(allow mach-lookup ...) ;; Mach IPC lookups
(allow mach-register ...) ;; Register Mach services
(allow ipc-posix-shm* ...) ;; POSIX shared memory
(allow ipc-posix-sem* ...) ;; POSIX semaphores
System operations:
(allow sysctl-read) ;; Read system info
(allow sysctl-write ...) ;; Modify sysctl (rare)
(allow iokit-open ...) ;; IOKit device access
(allow pseudo-tty) ;; Terminal emulation
(allow dynamic-code-generation) ;; JIT compilation
(allow user-preference-read ...) ;; Read user defaults
/tmp and /var/folders(version 1)
(deny default)
;; Process
(allow process-exec*)
(allow process-fork)
(allow sysctl-read)
;; File metadata (path resolution)
(allow file-read-metadata)
;; File reads (allowlist)
(allow file-read-data
(literal "/") (literal "/var") (literal "/etc") (literal "/tmp") (literal "/private")
(subpath "/usr") (subpath "/bin") (subpath "/sbin") (subpath "/opt")
(subpath "/System") (subpath "/Library") (subpath "/dev")
(subpath "/private/var") (subpath "/private/etc") (subpath "/private/tmp")
(subpath (param "WORKING_DIR")))
;; File writes (restricted)
(allow file-write*
(subpath (param "WORKING_DIR"))
(subpath "/private/tmp") (subpath "/tmp") (subpath "/private/var/folders")
(literal "/dev/null") (literal "/dev/tty"))
;; Network disabled
(deny network*)
Usage:
sandbox-exec -f profile.sb \
-D WORKING_DIR=/path/to/project \
-D HOME=$HOME \
/path/to/application
Weekly Installs
556
Repository
GitHub Stars
3.9K
First Seen
Feb 26, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex504
cursor503
github-copilot502
opencode502
gemini-cli501
kimi-cli500
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
138,300 周安装