跳转到主要内容

完全磁盘访问权限是一种粗放式授权:将智能体的读取权限限定到数据类别

macOS 的完全磁盘访问权限是对所有用户文件的一个布尔开关。持久的解决方案是按数据类别授予读取权限,并在每次读取时记录来源。

服务器机架的近景,显示网络电缆和指示灯,代表文件系统访问控制基础设施。

授权本身就是问题

Apple 收紧 macOS 完全磁盘访问权限(FDA)是对一个真实故障模式的合理回应:智能体框架、终端封装程序或后台辅助程序会请求尽可能宽泛的读取权限,因为精确的请求更难描述。结果就是一个覆盖用户可读取的所有文件的单一布尔开关。一个只需要一个项目目录的智能体,和一个只需要一个配置文件的智能体,获得了相同的权限。授予权限的成本很低,而对其推理的成本却很高。

这种不对称就是问题的全部。授予权限只需一个对话框。对其推理则需要对依赖它的每一个工作流进行审计,因为撤销并非按范围限定:撤销 FDA 会使恰好共享同一布尔开关的无关工作流失效。运维人员的应对方式是保留授权并将其视为环境基础设施,而这恰恰是收紧措施所要防止的情况。

更深层的问题在于,这种权限模型早于那些在每次读取时无需人工介入即可行动的智能体。当一个人打开文件时,这个人就是来源。当一个智能体代表某个任务读取文件时,这个任务就是来源,而平台没有地方记录它。FDA 可以告诉你某个东西读取了你的钥匙串。它无法告诉你哪个任务、哪个智能体,或者那次读取是否合法。

以数据类别作为范围限定原语

持久的解决方案是停止将文件系统范围的授权作为智能体授权的单位。改为按数据类别限定读取权限。数据类别是一组共享读取策略的路径,例如:

  • 凭据:钥匙串、.env 文件、SSH 材料、云服务商配置、浏览器凭据存储
  • 源代码树:版本控制的工作副本、monorepo 检出、vendored 依赖
  • 个人通信:邮件存储、消息数据库、日历和联系人存储
  • 构建产物:编译输出、缓存、容器层、包管理器存储
  • 系统配置:/etc、启动代理、网络配置文件

智能体请求的是一个类别,而不是一个路径。平台在授权时将路径解析为类别,并在读取时重新解析。构建智能体请求 source-trees 和 build-artefacts;部署智能体请求限定到某个服务商的 credentials 以及 build-artefacts;摘要智能体请求某个账户的 personal-communications。这种请求对人类审查者来说是可读的,而 ~/Projects 则不是,因为它陈述的是意图而非位置。

关键特性是类别成员资格由平台计算,而非由智能体声明。如果智能体可以断言“这个路径是构建产物”,那么把一个密钥重命名到 dist/ 中就会破坏这套分类法。解析应结合路径模式、文件元数据、内容信号和血缘:一个由持有凭据的进程写入的文件,即使被复制后,也应继承与凭据相邻的分类。被重命名的密钥仍然受到保护,因为它的类别源自它是如何产生的,而不是它当前所在的位置。

Two lab workers in protective gear carry sample trays through a sterile white laboratory hallway

每次读取都记录来源

如果没有对已发生事件的记录,仅靠范围限定是不够的。每个读取事件至少应携带三个字段:

{
  "agent_identity": "build-runner@ci-7",
  "task_id": "task-4f9c2a1e",
  "resolved_class": "source-trees",
  "path": "/Users/dev/work/api/src/main.rs",
  "decision": "allow",
  "policy_version": "2024-11-03"
}

任务标识符是大多数系统遗漏的字段,而它正是使审计记录可解释的关键。没有它,一条显示读取 ~/.aws/credentials 的日志行,与一个合法的部署步骤和一条数据外泄路径无法区分。有了它,运维人员就可以提出真正重要的问题:哪些任务读取了凭据,其中是否有任何任务在同一时间窗口内也读取了个人通信?只有当任务标识符出现在每次读取中,并从智能体的入口点传播到每次工具调用和子进程时,这个问题才能被回答。

记录解析决策与记录路径同样重要。一条记录显示某个路径的 resolved_class: source-trees,而策略现在会将其归类为 credentials,这就是一个漂移信号。没有这个决策,策略变更在出问题之前都是不可见的。有了它,漂移就可以通过查询检测到:找出解析类别与当前分类器不一致的读取。

一种具体的解析机制

一个可行的实现分为三个阶段。

分类。 一个后台分类器维护从路径模式和血缘记录到类别的映射。它在文件创建、重命名和内容变更时运行。分类是带版本的;每次读取都会记录当时生效的策略版本。

解析。 在Close-up of an orange power button on an electronic remote control:计算类别、策略版本,以及所需的授权。

Circuit board macro

来源发出。 运行时将带有上述字段的读取事件发出到仅追加的接收端。该接收端可按任务、智能体和类别查询,并且是漂移检测的基础。

有两个细节决定了这在实践中是否可行。首先,解析必须足够快,以位于读取路径上;一个以 inode 和策略版本为键的缓存通常就足够了,并在分类变更时失效。其次,拒绝必须是可操作的。一个显示 computed_class: credentials, required_grant: credentials:aws-prod 的拒绝,会准确告诉运维人员需要更改什么。一个显示 permission denied 的拒绝,则会教他们去授予 FDA。

这需要付出什么代价

诚实的权衡有三点。

延迟与维护。 类别解析在读取路径上增加了一次查找,而且分类法必须得到维护。特定领域的类别会随着团队重组其仓库而漂移。一个未被维护的分类法会成为误拒绝的来源,而误拒绝比宽泛授权更快地侵蚀信任。

合法拒绝。 智能体偶尔会被拒绝读取它们本应读取的内容。一个读取被分类器标记为与凭据相邻的生成文件的构建步骤将会失败。设计必须使这种拒绝可操作而非静默:呈现计算类别、策略版本,以及能解除任务阻塞的最窄授权。静默拒绝会产生与粗放授权相同的绕过行为。

供应商阻力。 平台供应商会抵制提供类别分类法,因为它们是特定领域的且难以默认设置。一个通用操作系统无法知道某个团队的 fixtures/ 目录包含合成数据,而另一个团队的包含生产快照。现实的路径是一小组平台定义的基础类别加上一个扩展机制,并理解扩展正是大部分价值和大部分维护负担所在。

这些都不是免费的,也没有一个是完整的答案。然而,它改变了授权的单位。FDA 问的是智能体是否可以读取一切。类别范围模型问的是这个智能体在这个任务上可以读取哪些类型的数据,并记录答案。第二个问题才是运维人员真正需要回答的问题,也是当前模型无法表达的问题。

封面照片:panumas nikhomkhai / Pexels。

分享XLinkedIn永久链接5 分钟阅读

相关阅读

这能回答的问题

Why is Full Disk Access the wrong unit of authorisation for agents?

It is a single boolean over every file the user can read, so an agent needing one project directory receives the same authority as one needing one config file. Revocation is unscoped, which makes the grant expensive to reason about and therefore rarely revoked.

What is a data class in this model?

A set of paths sharing a read policy, such as credentials, source trees, personal communications, and build artefacts. Agents request a class rather than a path, and the platform resolves paths to classes at grant time and re-resolves at read time.

Why should class membership be computed rather than declared?

If an agent could assert a path's class, renaming a secret into a build output directory would defeat the taxonomy. Computing class from path patterns, metadata, content signals, and lineage keeps a renamed secret protected.

Why does every read need a task identifier?

Without it, audit records cannot distinguish a legitimate build step from an exfiltration path. The task identifier lets operators ask which tasks read credentials and whether any also read personal communications in the same window.

What are the main costs of class-scoped read rights?

Resolution adds a lookup on the read path, the taxonomy must be maintained, legitimate agents will occasionally be denied, and vendors resist shipping domain-specific taxonomies as defaults. The denial must be actionable rather than silent.