macos应用沙箱是强制运行前提,基于xnu内核隔离,仅默认访问自身容器目录、tmp及用户主动授权的文件;访问documents等需通过nsopenpanel选中+安全书签持久化+配对启停资源访问;权限由.entitlements声明与tcc运行时控制共同决定;跨应用通信须经xpc、url scheme等系统背书机制。
macos 的应用沙箱化不是附加功能,而是运行前提——所有从 mac app store 下载或启用 hardened runtime 的第三方应用,默认都处于沙箱中。它不靠“关文件夹门”实现隔离,而是在内核层(xnu)就划清边界:每个应用只能看到自己的容器目录,连读一个桌面文件都得先弹窗问用户。
沙箱默认能碰什么?
沙箱应用天然拥有以下路径的完整读写权限:
- 自身容器目录:
~/Library/Containers/com.example.app/Data/(含 Documents、Caches、Preferences 等子目录) - 临时目录:
~/Library/Containers/com.example.app/Data/tmp/ - 用户通过 NSOpenPanel 或 NSSavePanel 主动选中的单个文件或文件夹(需配合安全书签才能复用)
想访问 Documents、Downloads 怎么办?
不能硬编码 ~/Documents 去 open(),必须走系统认证路径:
- 首次访问:调用
NSOpenPanel,设canChooseDirectories = true,让用户点选目标文件夹 - 获取持久凭证:对选中 URL 调用
bookmarkData(options: .withSecurityScope),把二进制书签存进自己容器内(比如Application Support目录) - 下次启动时:用
URL.resolvingBookmarkData(_:)恢复 URL,再调startAccessingSecurityScopedResource()才能真正读写 - 每次访问完必须配对调
stopAccessingSecurityScopedResource(),否则资源锁不释放
权限声明与运行时控制
权限不是装上就生效,而是由两层共同决定:
-
编译期声明:在
.entitlements文件里明确写入,例如com.apple.security.files.user-selected.read-write,Xcode Capabilities 里勾选会自动生成 - 运行时授权:TCC 数据库记录每项权限状态,用户可在「系统设置 → 隐私与安全性」中随时开关,撤销后能力立即失效,无需重启应用
跨应用协作怎么安全通信?
沙箱之间不共享内存、不直连文件句柄,所有交互必须经系统背书:
- XPC 服务:双方需在 entitlements 中声明匹配的
com.apple.application-identifier和 service bundle ID - URL Scheme:必须在 Info.plist 中预注册,否则
openURL:直接失败 - 拖放与剪贴板:系统自动校验来源应用沙箱身份,非法来源数据被静默过滤
- Keychain 访问:需配置
keychain-access-groups,且签名证书一致,否则SecItemAdd返回errSecInteractionNotAllowed











