授权范围比任务更宽
macOS 上的完全磁盘访问权限(FDA)是一项单一的 TCC(透明度、同意与控制)授权,它解除了沙箱在整个主目录范围内的读取屏障。实际上,一次批准就覆盖了 Mail 存储、Safari 和 Chrome 的配置文件目录、登录钥匙串、Messages 数据库,以及任何位于 ~/.aws、~/.ssh 或 ~/.config 中的开发者凭据。用户看到的是一个对话框和一个开关。系统看到的是一位。
这一位是持久的。它能在重启后存活,适用于该已签名二进制的每一次未来调用,而且不会因为进程的启动方式而收窄。一个在周二只需要读取单个项目文件夹的 agent,到了周五被要求总结下载目录中的一份 PDF 时,仍然持有同样的授权。
Agent 工作负载是分段的。一次运行有开始、有计划、有一组工具调用,也有结束。运行所需与授权所允许之间的差距就是风险面,而在 macOS 上,这个差距目前就是整个主目录。
为什么应用程序模型不适用
经典的 macOS 应用程序拥有稳定、可审计的功能集。照片编辑器读取图像。邮件客户端读取邮件存储。审查者可以就权限进行推理,因为行为受产品用途的约束。
Agent 的读取集合由规划器在运行时决定。同一个二进制被调用两次,可能在一个会话中读取电子表格,在下一个会话中读取钥匙串文件,因为计划是根据提示词和环境生成的。不存在描述该进程将触及哪些内容的静态清单。
这改变了提示词注入的失效模式。在传统应用中,注入可能导致糟糕的输出。而在持有 FDA 的 agent 中,注入无需任何权限提升,就能把一项合法授权变成一条数据外泄路径:模型已经被授权读取凭据,网络工具也已经被授权发送字节。攻击者不需要攻破沙箱;他们只需要操纵计划。

与此同时,用户被要求对一个写着“访问所有文件”的对话框进行推理,而任务却是“总结这个文件夹”。对话框无法表达任务,因为操作系统并不知道任务是什么。因此,这种同意在真正重要的特定意义上是无知的:它并未按用户实际正在做的决定来划定范围。关于 Apple 收紧这些控制的报道一直聚焦于应用开发者的体验(The Verge、TechCrunch);agent 的情况在结构上不同,因为请求方并非固定的功能集。
一种按任务划定范围的替代方案
控制权应当从二元的操作系统权限转移到按任务划定范围的能力契约。操作系统授权成为上限;agent 框架成为将其收窄的执行点。
一个具体机制:为每次运行签发一个限定范围的处理句柄。该句柄是一条包含四个字段的小记录。
- 路径。 一份显式的目录或文件允许列表,在计划时解析,而非在授权时解析。符号链接会被解析,被检查的是解析后的路径。
- 时间窗口。 一个墙钟过期时间。过期之后,即使进程仍然存活,该句柄也失效。
- 字节预算。 一个累计读取上限。当预算耗尽时,后续读取会失败关闭,而不是静默截断。
- 终态。 一条完成即撤销的规则。当运行到达终态(成功、失败、超时、取消)时,句柄被销毁,审计记录被封存。
handle = broker.issue(
paths=["~/work/reports/q3"],
ttl_seconds=600,
byte_budget=64 * 1024 * 1024,
revoke_on=["run.completed", "run.failed", "run.cancelled"],
)
# every read goes through the hanmd")

每一次读取都在句柄边界处被记录,这使得审计轨迹是按任务而非按二进制。当出问题时,“这次运行触及了什么”这个问题有了直接答案,而不是从进程级遥测中重建。
权衡是真实存在的,值得直说。一个中介读取的 broker 增加了一个可能失败的组件,而过于紧张的字节预算会中止合法的长时间运行作业。因此,框架必须把预算暴露给规划器,使 agent 能在撞墙之前请求扩展,而不是在运行中途以异常的形式发现限制。这比单个 TCC 开关涉及更多活动部件,而这正是让权限变得有意义的代价。
这对 macOS agent 开发者意味着什么
为一个不鼓励宽泛授权的世界而设计。优先使用文档选择器、安全作用域书签和按目录授权,而不是单一的 FDA 批准。指向单个文件夹的书签是比整个主目录读取更窄的能力,而且它可以在每次运行时被持久化并重新验证。
假设授权会在通知中对用户可见,并让该通知有意义。如果系统显示“此 agent 读取了你的 Messages 数据库”,agent 应当能够说明是哪个任务导致的,以及数据被用于什么。用户无法据以行动的通知会训练他们忽略通知,这会降低对所有其他应用的控制效果。
为运行中途的撤销做好规划。句柄可能过期,书签可能失效,用户可能在 agent 工作时关闭授权。Agent 应当是可恢复的,而不是致命的:对计划做检查点,标记失去能力的那一步,然后要么请求一个范围更窄的新句柄,要么带着部分结果干净地停止。把撤销当作崩溃,会把一项安全控制变成一次可靠性事故,而控制就是这样被禁用的。
更广泛的一点是,信任的单位应当与工作的单位相匹配。一次 agent 运行是工作的单位。二进制的生命周期不是。在权限模型反映这一点之前,macOS 上的每一个 agent 都距离一次提示词注入仅一步之遥,可能读取远超其任务所需的内容。
封面照片:Jakub Pabis / Pexels。
