macOS 应用沙盒通过内核层边界隔离实现权限控制,应用默认仅能访问自身容器、临时目录及用户显式授权的文件或系统资源;所有越界调用被XNU拦截并返回EPERM;权限需代码调用与entitlements、Info.plist配置严格匹配;文件访问必须经NSOpenPanel等授权路径并正确管理安全书签;跨应用通信须用XPC且预声明,敏感行为受TCC独立管控。

沙盒强制最小权限,越界访问直接被内核拦截
启用沙盒后,第三方应用无法直接访问 ~/Documents、~/Desktop、/Applications 等路径。任何未经授权的系统调用(如 open() 或 connect())都会被 XNU 内核的沙盒策略引擎拦截,并返回 EPERM 错误,明确表示“操作被策略拒绝”,而非普通权限不足。
沙盒应用天然可读写的路径只有:
- 自身容器目录:
~/Library/Containers/<bundle-id>/Data/(含 Documents、Caches、Preferences 子目录) - 临时目录:
~/Library/Containers/<bundle-id>/Data/tmp/ - 用户通过
NSOpenPanel或NSSavePanel显式选择的单个文件或文件夹(需配合安全书签复用) - 经声明并获授权的系统资源(如照片库、通讯录、麦克风等)
权限必须显式声明,且代码与配置严格匹配
仅在代码中调用 API 不够,Xcode 中必须同步完成三项关键配置:
- 在 Signing & Capabilities 中开启 App Sandbox,生成
com.apple.security.app-sandboxentitlement - 勾选对应功能权限,例如“User Selected File Access”会自动添加
com.apple.security.files.user-selected.read-write - 若使用安全书签持久化访问,还需启用 “App Sandbox Bookmarks”,添加
com.apple.security.files.bookmarks.app-scope
常见失败原因包括:entitlements 缺失对应键值、Info.plist 没配 usage description(如访问照片库缺 NSPhotoLibraryUsageDescription)、临时例外(temporary-exception)用于发布版本(Mac App Store 审核直接拒绝)。
文件访问必须走用户授权路径,不能硬编码路径
第三方软件不能写死 ~/Downloads 去读取文件,必须依赖用户主动交互:
- 用
NSOpenPanel弹出系统 Powerbox 对话框,设置canChooseDirectories = true - 调用
url.startAccessingSecurityScopedResource()开启本次访问权限 - 读写完成后,立即调用
url.stopAccessingSecurityScopedResource() - 若需重启后仍可访问,调用
url.bookmarkData(options: .withSecurityScope)生成书签数据,并存入自身容器(如Application Support目录) - 下次启动时,用
URL.resolvingBookmarkData(_:)恢复 URL,并再次startAccessing
漏掉 start/stop 配对、把书签存到非沙盒路径(如 /tmp)、未处理 isStale 返回值,都会导致 Operation not permitted。
跨应用通信和敏感行为也受沙盒约束
沙盒不仅管文件,还限制进程间协作与界面暴露:
- 两个 App 想交换数据,不能共享内存或文件句柄,必须走 XPC 或 NSXPCConnection,且 service bundle ID 需在 entitlements 中预声明
- 拖放、剪贴板共享、URL Scheme 调用均受校验,URL Scheme 必须在 Info.plist 中注册,否则启动失败
- Alt-tab 切换、Mission Control 缩略图可能暴露密码管理器等敏感窗口,建议用支持黑名单的工具(如 alt-tab-macos)隐藏特定应用
- 辅助功能权限(如自动化、屏幕录制)由 TCC 数据库独立管理,按账户、按 App 记录授权状态,用户可随时撤销


















