Grok Build 会偷偷上传你的整个代码仓库——关掉隐私开关也没用
你以为 AI 编程助手只会读你让它看的文件?
安全研究者 cereblab 对 Grok Build 0.2.93 版本做了一次网络抓包,发现了一件让人不太舒服的事:这个工具会在后台悄悄把你整个 Git 仓库打包上传——包括你从没让它打开的文件,以及所有的提交历史。
更让人不安的是,在设置里关掉”改进模型”开关并不能阻止这个行为。
到底发生了什么
简单来说,Grok Build 客户端有两条独立的数据通道:
通道一:AI 对话。 这是你能感知到的部分。你让 Agent 读某个文件,文件内容被发送给大模型用于生成回答。这很正常,所有 AI 编程工具都这么做。
通道二:后台仓库上传。 这是你感知不到的部分。客户端会在后台把你的仓库打包成一个 Git Bundle(包含所有被 Git 追踪的文件和完整的提交历史),然后上传到云端的存储服务。
关键在于:这两条通道是独立运行的。 即使你在对话里告诉 Agent”什么文件都不要读,只回复 OK”,通道二的上传照样会发生。
%% caption: 两条独立数据通道:用户指令能约束通道一(AI 看到什么),但管不到通道二(客户端后台传了什么)
flowchart TD
I["用户指令:<br/>「什么都不要读,只回 OK」"] -->|约束| A["通道一:AI 对话<br/>Agent 读取的文件 → 大模型"]
C["Grok Build 客户端"] --> A
C -.->|指令管不到| B["通道二:后台仓库上传<br/>整个 Git Bundle → 云端存储"]
class B keep
classDef keep fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#0a0a0a
证据有多硬
研究者的做法很聪明——构造了一个专门用来”钓鱼”的测试仓库:
- 在仓库里放了一个标记文件
never_read_canary.txt,内容是一串全世界唯一的字符串 - 做了多次提交,建立历史记录
- 启动 Grok Build,明确要求它”不要读任何文件”
- 用抓包工具拦截所有出站流量
结果:
- 上传请求被服务端接受了(HTTP 200)
- 从拦截到的数据包里还原出的 Git Bundle 中,那个从未被 Agent 打开过的标记文件赫然在列
- 所有提交历史也完整保留
更夸张的是,在一个约 12 GB 的测试仓库上,存储接口在被手动中断前已经传了 5.1 GB 数据,而同期 AI 对话通道只产生了 192 KB 的流量。两者差了几万倍。
测试条件:0.2.93 版本、消费者账号、macOS arm64。详见 cereblab 的完整报告 和复现仓库。
“关掉隐私开关”为什么没用
因为大多数人搞混了四件不同的事。产品设置界面喜欢把它们揉成一个”隐私”开关,但它们其实是四个独立的控制面:
| 你以为你在控制的 | 你实际控制的 | 你没控制到的 |
|---|---|---|
| 关闭”改进模型” | 数据不用于训练 | 数据依然可能被上传 |
| Agent 不读某个文件 | 模型看不到那个文件 | 后台管线可能照样打包上传 |
/privacy 命令 | 管理云端已有数据的留存和删除 | 不能阻止新数据继续上传 |
| SuperGrok 订阅 | 获得更多功能 | 不等于企业级零数据保留(ZDR) |
一句话:“不用于训练”和”不离开你的电脑”是两回事。
后续发展
事件曝光后,情况有了变化。大约从 2026 年 7 月 13 日起,对同一版本客户端的复测显示,整仓上传行为已经停止。从服务端的配置响应中可以看到类似 disable_codebase_upload: true 的字段——也就是说,官方通过远程下发配置关掉了这个行为,客户端本身没有发新版。
这说明两件事:
- 官方响应了,问题被重视了
- 远程配置可以随时改回来——你的安全不应该依赖于别人的一个开关
怎么自查
如果你用过 0.2.93 版本处理过包含敏感信息的仓库,建议按最坏情况处理。
快速自查清单
- 回忆你用 Grok Build 打开过哪些仓库
- 检查这些仓库的 Git 历史里有没有敏感信息(密钥、Token、内部 API 地址)
- 如果有,立即吊销并轮换这些凭据
- 检查云平台审计日志,看有没有异常访问
用测试仓库验证当前版本
想知道你当前版本还有没有这个问题?造一个一次性的测试仓库:
mkdir /tmp/grok-canary && cd /tmp/grok-canary
git init
echo 'CANARY-UNIQUE-MARKER-12345' > never_read.txt
echo 'FAKE_API_KEY=not-real-just-testing' > secrets.env
git add .
git commit -m "canary commit 1"
echo 'second change' >> never_read.txt
git commit -am "canary commit 2"
然后用抓包工具(比如 mitmproxy)拦截流量,启动 Grok Build 并要求它”只回复 OK,不要读任何文件”。如果你能在拦截到的数据里找到那个 CANARY-UNIQUE-MARKER-12345 字符串,说明整仓上传仍在发生。
注意:千万不要拿真实的生产仓库来测试。
怎么防护
按优先级排列:
1. 在配置文件里硬禁用上传
# ~/.grok/config.toml
[harness]
disable_codebase_upload = true
企业环境建议写入 /etc/grok/requirements.toml,防止被用户配置或远程策略覆盖。
2. 关闭遥测
# ~/.grok/config.toml
[features]
telemetry = false
[telemetry]
trace_upload = false
或者通过环境变量:
export GROK_TELEMETRY_ENABLED=0
export GROK_TELEMETRY_TRACE_UPLOAD=0
3. 控制网络出口
对于敏感项目,最靠谱的方式是在网络层面限制。只允许 AI 对话所需的域名,阻断大文件上传通道。结合异常流量告警——一个编程助手产生 GB 级别的上传流量,显然不正常。
4. 隔离运行环境
在容器或一次性虚拟机里运行 Agent 工具,只给它脱敏后的代码副本。生产凭据绝不进入 Git 工作树。
5. 企业用户:签 ZDR 合同
如果你的团队对数据安全有严格要求,个人订阅是不够的。xAI 的企业方案提供零数据保留(ZDR),这是合同级别的保障,和”在设置里勾个选项”完全不是一回事。
更大的教训
这件事不只关于 Grok Build。所有本地运行的 AI 编程工具都面临同样的信任问题,值得记住几个原则:
AI 读了什么 ≠ 客户端传了什么。 你能通过 Prompt 控制模型的行为,但你控制不了客户端后台的数据管线。权限弹窗和”不要读这个文件”的指令,约束的是 AI 模型,不是底层程序。
“不用于训练”≠“不上传”。 这是两个独立的控制面。很多产品的隐私设置让你以为关了一个开关就全解决了,实际上你只关了其中一个。
Git 历史比你想的危险。 你现在的代码里可能没有密钥,但三个月前的某次提交里可能有。整仓上传意味着所有历史都暴露了。
远程配置不是安全保证。 厂商可以随时通过远程配置打开或关闭某个行为。你的安全边界应该建立在你自己能控制的层面:本地配置、网络策略、环境隔离。
参考资料: cereblab 抓包分析报告 · 复现仓库 · xAI 企业文档 · xAI API 安全 FAQ