这个权限本来是给备份用的
10 月 2 日,Apple 表示将为 macOS 的完全磁盘访问权限加上新的管控。这个设置原本是为了让备份 App 正常工作,但“随着 AI 代理变得越来越强大、越来越自主,这种级别的访问所带来的风险将大幅增加”。导火索是 Meta 的 Muse:一位记者说它把他的信息数据库同步到了第 187,462 行;另一件是 Patrick Wardle 在 ChatGPT Mac App 中发现的漏洞。编程代理可以从启动它的终端继承同样的访问范围,而它能读到的开发者机密,从来就不在这个权限的保护之下。在 Bromure Agentic Coding 中,代理不是 Mac 上的进程:它运行在一台 Linux VM 里,VM 中只有你共享的文件夹和替身凭据。
Apple 打造完全磁盘访问权限,是为了让备份 App 能读取一切。如今 AI 代理要求同样的访问范围,而在开发者的 Mac 上,它们往往不用开口,就从终端那里拿到了。
10 月 2 日,Apple 在开发者新闻页面上发布了一则简短公告,标题是 Updates to Full Disk Access in macOS。公告解释了这个设置存在的原因:“完全磁盘访问权限在很大程度上绕过了这些管控,以便备份 App 能在 Mac 上正常工作。”接着描述了部分开发者拿它做了什么:“在用户未充分知情和理解的情况下,暴露了他们系统上的一切,包括文件、邮件、信息,甚至浏览历史。”
Apple 将增加管控,让想授予这种访问权限的用户“只能通过非常明确的用户操作”来授予。Apple 也说明了现在采取行动的理由:“随着 AI 代理变得越来越强大、越来越自主,这种级别的访问所带来的风险将大幅增加。”
Apple 没有给出日期,也没有说明已有的授权会如何处理。但这则公告清楚表明了 Apple 怎么看待落到代理手里的完全磁盘访问权限。
两周内的两条新闻
对这则公告的报道, 从 TechCrunch 开始,都把它和两起事件联系在一起。
Muse 与信息数据库。 9 月 19 日,Inc. 专栏作家 Jason Aten 报道,他 Mac 上的 Meta Muse 代理发来一条通知,建议他以刚刚和播客联合主持人的对话为题写一篇专栏。他说自己拒绝了 Muse 访问信息的请求,却发现 Muse 已经把他的信息数据库同步到了第 187,462 行,而 Muse 自己的设置显示完全磁盘访问权限是关闭的。 Meta 对这一说法提出异议。Meta Superintelligence Labs 的 David Singleton 表示,Muse 必须经过“三个独立步骤,包括应用级别的权限和 macOS 内置的系统级保护”才能读取信息,而这些保护“即使 Muse 应用有 bug 也无法绕过”。Muse 自己则告诉 Aten,它一直在同步他的设备通知。
Objective-See Foundation 的 Patrick Wardle 总结了 App 一旦拿到这个权限意味着什么:“任何(非 root 的)文件都可读取,浏览历史、浏览器 Cookie、聊天记录等等。”
ChatGPT 的 Mac App。 同一周,Wired 报道了 Wardle 在 OpenAI macOS 版 ChatGPT App 中发现的漏洞 CVE-2026-100754。这个 App 根据代码签名和进程的父子关系来决定信任哪些本地进程。一个受信任的脚本解释器可以被喂入不受信任的输入,让已经在 Mac 上运行的普通代码混进一条被接受的进程链,进而操控 App 的受信任功能:聊天记录,以及浏览器会话等已连接的集成。OpenAI 在构建版本 26.924.20706 中修复了这个漏洞,该版本自 9 月 25 日起上线。目前没有任何实际被利用的报告。
两条新闻的前提相同。Mac 上的代理以你的身份运行,凡是它能读到的,任何接管这个代理的代码也都能读到。
终端早就同意了
Muse 是通过系统设置申请完全磁盘访问权限的,正如 Apple 的模型所预期。终端里的编程代理什么都不申请,直接沿用终端的授权运行。
macOS 会针对负责的 App 检查隐私权限,对命令行工具而言,就是启动它的那个终端。许多开发者多年前就给了终端、iTerm
或编辑器完全磁盘访问权限,好让 find、rsync 或备份脚本不再弹出询问。从那个窗口启动的每个进程都会继承这份授权。这包括 Claude
Code、Codex 和 Gemini CLI,以及 npm install 的每个 postinstall 脚本、它们启动的每个 MCP 服务器,还有每一条被 README
说服而执行的单行命令。
在这种配置下,Apple 列出的文件,代理和代理运行的一切都够得着:
~/Library/Messages/chat.db,也就是 Muse 被指控同步的信息记录~/Library/Mail,每一个邮箱- Safari 的浏览历史和 Cookie,位于
~/Library/Safari及其容器中 - 备忘录、照片图库,以及其他 App 的私有容器
机密从来不在询问弹窗后面
Apple 的改变是对的,它保护了大家认为是隐私的文件。但开发者工作用的凭据放在别处。下面这些路径,既不受完全磁盘访问权限保护,也不受 macOS 任何其他隐私权限保护:
~/.ssh/id_ed25519~/.aws/credentials和~/.aws/sso/cache/~/.config/gh/hosts.yml、~/.git-credentials、~/.npmrc、~/.docker/config.json、~/.kube/config- 你克隆过的每个项目里的
.env文件 - 代理本身的 OAuth 令牌和会话记录
任何以你的用户身份运行的进程都能读取它们,不论有没有完全磁盘访问权限。Apple 的新管控会让一个大权限更难授予。但笔记本上的编程代理本来就不需要这个权限,就能拿到让攻击者推送到你的仓库、或打开你 AWS 账户的文件。针对编程代理的信息窃取程序已经在收集这些文件:访问令牌和刷新令牌、MCP 配置、提示历史。
在检查哪些 App 拥有完全磁盘访问权限之前,先看看代理的电脑里有什么。
在 Bromure 中,代理不是 Mac 上的进程
Bromure Agentic Coding 在 Apple Virtualization.framework 之下的 Ubuntu VM 中运行每台机器的代理。Claude Code、Codex、Grok 等都是 Linux 内核上的 Linux 进程。它们从不打开 Mac 文件系统上的文件,所以 macOS 的隐私权限对它们不适用。没有可以继承的授权,也没有会把权限泄漏给代理的终端,因为你在 Bromure 中看到的终端连接的是 VM,而不是你 Mac 的 shell。
VM 看得到的东西,只有短短一张清单:
- 它自己的系统磁盘,是一份已签名 Ubuntu 镜像的写时复制(copy-on-write)克隆。
- 它自己的主目录
/home/ubuntu,放在一个私有的磁盘镜像上。 - 你和这台机器共享的文件夹,最多八个,各自以名称挂载在主目录下。如果你共享
~/code/payments,代理看到的是~/payments。它看不到~/code,也永远看不到~/Library。 - 每次启动的一个小型配置共享,只读,存放代理服务器设置和替身凭据。
chat.db 不在这张清单上,邮件和 Safari 的浏览历史也不在。一个像 Muse 那样的同步任务,或是一个遭到提示注入、被要求“把我最近的信息整理成摘要作为上下文”的代理,只会发现
~/Library/Messages 根本不存在。VM 里没有任何路径通往那里。
开发者机密都是替身
这样就覆盖了 Apple 的清单。Bromure 也覆盖了 Apple 公告略过的那张清单:dotfiles。
真正的凭据加密后留在 Mac 上。VM 拿到的是格式正确的替身:GH_TOKEN 是 ghp_ 加上 36 个 GitHub
会拒绝的字符,ANTHROPIC_API_KEY 是 sk-ant-api03-brm-…,而 ~/.git-credentials、~/.docker/config.json 和
~/.kube/config 里放的都是假的。Mac 上的代理服务器会在请求离开 VM 之后才填入真正的值,而且只在请求要发往该凭据所属的主机时才这么做。用手册的话来说:“VM
内的任何文件、环境变量或进程,都不会包含真正的 API 密钥、OAuth 令牌、AWS 密钥或 SSH 私钥。”
有两个细节回应了 Apple 对大范围授权的担忧:
- AWS 导入只要求 Mac 上的一个文件夹。 导入你的 AWS 配置文件时,Bromure 只针对
~/.aws请求一份 security-scoped 授权。这个文件夹在 Mac 上读取,从不挂载进 VM。这正是 Apple 公告所要求的那种范围窄、意图明确的授权,而且它给的是宿主 App,从来不是代理。 - SSH 密钥留在 Mac 上。 VM 的
SSH_AUTH_SOCK是一座通往 Mac 上 SSH agent 的桥。客户机可以请求签名,但私钥的字节从不进入 VM。你 macOS 登录会话的 ssh-agent 也从不暴露给它。
当 Claude Code 通过 Bromure 登录时,OAuth 流程在你 Mac 的浏览器里进行,令牌存放在 Mac 上。VM 的 ~/.claude
里没有任何真正的令牌。而那正是针对编程代理的信息窃取程序要找的文件。
浏览器也有自己的磁盘
Apple 提到了浏览历史,Wardle 提到了 Cookie。Bromure 中的代理有一个浏览器,是代理通过内置 browser MCP
服务器操控的完整 Chromium。它运行在第二台用完即弃的 VM 里,和代理的机器、和你的 Mac 都是分开的。默认情况下,它的磁盘是一份临时克隆,浏览器关闭时就会删除,所以
Cookie、登录状态和浏览历史都会随之消失。它无法访问 Safari 的浏览历史或你桌面版 Chrome 的配置文件,因为那些都在 Mac 上。
一切外流都要经过 Mac
假设代理真的从你共享的项目文件夹里收集到值得偷的东西。它只有一条出路。VM 的虚拟交换机会把每个网络连接导向 Mac 上的代理服务器,而客户机无法关掉这个机制。
- 在默认的追踪级别下,每个请求都会写进 Mac 上的加密追踪记录,与模型的往来内容会被拆解成代理发出的工具调用和 shell 命令。Trace Inspector 会在 POST 发往陌生主机的当下就把它显示出来。
- 机器的出站防火墙在 Mac 上执行,可以只允许项目需要的主机,其余一律丢弃。
- 如果载荷里带着某个替身凭据,代理服务器会发现一个凭据正被发往不属于它的主机。它会返回 HTTP 451、暂停 VM,并在 Mac 上弹出警报:This environment may have been compromised。
本地 IPC 手法需要 Mac 上的进程
CVE-2026-100754 的前提是“已经在 Mac 上运行的非特权代码”能触及 ChatGPT App 的本地信任通道。在笔记本上,以你的身份运行的代码,最活跃的来源往往就是编程代理:它安装的依赖、它运行的脚本、它下载的工具。在 Bromure 中,这些代码都在 Linux 客户机里运行。Mac 的 XPC 服务、Unix socket,以及背后的桌面 App,都在另一个内核里。VM 中的恶意 postinstall 脚本无法加入 Mac 上的进程链。
一项工作一台机器
共享文件夹决定了代理能看到多少。每台 Bromure 机器都有自己的文件夹列表、自己的凭据和自己的主目录,所以好习惯很容易养成:
- 每个项目都用一台专属的机器,只共享那个项目的文件夹。
- 只给机器它的项目用得到的凭据。用来试新 MCP 服务器和代理插件的实验机器,一个都不给。
- 保持 Prompt before write 开启,这是新机器针对 GitHub、云服务商、镜像仓库、Kubernetes 和数据库的默认值。推送和删除会停下来,等待一个显示确切操作内容的 macOS 对话框。
- 永远不要共享你的主目录。代理不需要它。
每次机器启动也会为主目录创建一个写时复制的检查点,所以 Rewind home… 可以找回代理在那里删掉的东西。
没有可继承的 macOS 权限
代理是 VM 里的 Linux 进程。它从不在你终端的完全磁盘访问权限之下运行,信息、邮件和 Safari 的数据也不在它的磁盘上。
只有你挑选的文件夹
每台机器只看得到自己的主目录,以及你按名称共享的最多八个文件夹。你 Mac 的其余部分,包括 ~/Library,都不在那里。
dotfiles 里都是假的
Git、云、镜像仓库和模型的凭据都是替身。SSH 私钥从不进入 VM。Mac 上的代理服务器在传输途中填入真正的值。
每条出路都有记录
网络流量经过主机上的代理服务器:被追踪、被出站防火墙过滤,替身一旦发往错误的主机,就连同 VM 一起暂停拦下。
给代理一台自己的电脑
Apple 的公告,是一家操作系统厂商告诉开发者:为备份软件设计的权限,不该交给自主代理。Apple 说得对。它的解法是更清楚的询问弹窗,而用户仍然得在一台存放着自己一切的 Mac 上,为每个 App 做出正确的选择。
Bromure 给代理一台自己的电脑。上面有你共享的项目,以及只有在你 Mac 上的代理服务器换上真货时才有效的密钥。等 Apple 的新对话框推出时,你的编程代理不会是弹出它的 App 之一。