TCC = Transparency, Consent, and Control,是 Apple 的隐私权限管理系统:应用第一次访问受保护资源时,系统弹窗征求用户同意,并把这次选择持久化记录下来,之后按记录放行或拒绝。2013 年随 macOS 10.9 Mavericks 引入,后来同样用于 iOS。
一句话概括三个词的含义:
- Transparency(透明):应用访问敏感资源前必须显式声明用途(purpose string),系统据此展示弹窗理由。
- Consent(同意):是否授权由用户决定,而不是由应用自行决定。
- Control(控制):授权结果被持久保存,用户可随时在系统设置里查看、撤销或重置。
管什么
TCC 守护的是「受保护资源」(protected resources),常见类别:
| 类别 | 代表服务 | 备注 |
|---|---|---|
| 摄像头 / 麦克风 | Camera / Microphone | 弹窗授权 |
| 通讯录 / 日历 / 提醒事项 | AddressBook / Calendar / Reminders | 个人数据 |
| 照片 | Photos | |
| 屏幕录制 | ScreenCapture | 截图、录屏、远控必需 |
| 辅助功能 | Accessibility | 自动化控制其他应用必需 |
| 完全磁盘访问 | SystemPolicyAllFiles | 读写受保护目录 |
| 文件与文件夹 | SystemPolicyDesktopFolder 等 | 桌面/文稿/下载等 |
位置服务(Location Services)不在 TCC 数据库里。它由
locationd单独管理,重置 TCC 不会影响位置权限。
权限记录存在哪
TCC 的授权记录是 SQLite 数据库,分用户级和系统级两份:
| 数据库 | 路径 | 说明 |
|---|---|---|
| 用户级 | ~/Library/Application Support/com.apple.TCC/TCC.db | 当前用户的授权 |
| 系统级 | /Library/Application Support/com.apple.TCC/TCC.db | 全局/系统服务授权 |
这两个文件都受 SIP(System Integrity Protection) 和 TCC 自身的保护,正常运行时无法直接读写;要手工改库必须先关 SIP,风险很高,通常不建议。
用 tccutil 重置授权
Apple 官方提供的 tccutil 是唯一受支持的重置入口,主要用途是让应用「重新弹一次权限请求」:
# 重置某个服务对所有应用的授权
tccutil reset Camera
# 重置某个服务对单个应用的授权
tccutil reset ScreenCapture com.example.App
# 重置某应用的所有权限
tccutil reset All com.example.App
# 重置所有应用的所有权限(核选项)
sudo tccutil reset All几个容易踩的点:
- 服务名区分大小写,且 Apple 没有公开完整列表,写错会静默不做或报错。
- 默认只影响当前用户账户;
sudo才会作用到所有用户账户。 - 应用已从磁盘删除时,
tccutil会报No such bundle identifier(OSStatus -10814),但数据库里的陈旧条目仍会保留,系统设置里也还能看到。 - 终极手段是在恢复模式下删除
TCC.db,先tccutil reset All再删以免两份库不一致;不到万不得已不要用。
为什么和「应用身份」强绑定
TCC 记录的不是「某个路径」,而是应用的签名身份(bundle ID + 代码签名)。这带来几个直接后果:
- 应用被重新签名、重打包、改名或换了 Team ID 后,原有授权会被视为另一个身份,需要重新授权。
- 无签名或临时签名的可执行文件,即使在终端里直接运行,也可能拿不到稳定授权——macOS 会把权限归属到「责任进程(responsible process)」,而不是随便一个二进制路径。
- 因此正确做法是把权限授予一个有稳定签名身份的 .app,再让它去启动子进程,而不是给裸二进制授权。
这也是 cua 在 macOS 上强调「用签名过的 App 持有 Accessibility / Screen Recording 授权」的底层原因;同理,screencapture 的屏幕录制能力、以及 macos-app-backup-and-reinstall 里提到的特权组件,都受 TCC 约束。
排障思路
权限「明明给过却还是不行」时的常见顺序:
- 在「系统设置 → 隐私与安全性」确认条目存在且开关是开的。
- 用
tccutil reset <服务> <bundle-id>重置该应用,让它重新弹窗。 - 确认应用身份没变(重签名、升级、迁移路径都会改变身份)。
- 仍然异常再考虑系统级重置,最后才是恢复模式删库。
相关页面
- cua — macOS 桌面自动化依赖签名 App 持有 TCC 授权(Accessibility / Screen Recording)
- screencapture — 截图与录屏受屏幕录制权限约束
- macos-app-backup-and-reinstall — 特权组件与重装恢复,涉及系统级授权归属