有研究者给 xAI 的官方编程 CLI Grok Build(版本 0.2.93)下了一道明确指令:“回复 OK,不要读取任何文件。”按理说,模型不读文件,数据就不该离开本地。结果抓包一看,整个代码仓库——包括一个从没被打开过的密钥文件、外加完整的 git 历史——原样打包成 git bundle,发到了 xAI 的服务器上,状态码 200。

这不是模型多读了一行代码的小事故,而是一套跟“模型看没看”完全脱钩的上传机制。

发生了什么

研究者用 mitmproxy 截获了 Grok CLI 的全部网络请求,做了三组实验:

  • 一个真实仓库里放一个从未被要求读取的密钥文件,结果它连同全仓库历史被打包上传,git clone 出来密钥原样可见。
  • 一个 12GB、全部由随机文件组成、模型从未读取过的仓库,存储通道 /v1/storage 传出了 5.10 GiB,全部 HTTP 200;同一时间模型对话通道 /v1/responses 只传了 192 KB
  • 两者相差约 27800 倍——模型不可能在 192KB 里装下 5GB 的内容,说明这 5GB 走的是另一条完全独立的通道。

目的地是 Google Cloud Storage 的 grok-code-session-traces 桶,不是常见的 AWS S3。二进制文件里能直接 strings 出这套机制的源码路径,来自一个叫 xai-data-collector 的 Rust 组件,说明这不是意外泄漏,而是产品里内建的一等功能。

12GB仓库测试:两条通道传了多少 5.10 GiB /v1/storage 存储通道 全部HTTP 200 192 KB /v1/responses 对话通道 模型实际看到的量 ≈27800× 上传/读取比例 与“是否读过”无关 模型端只见192KB,存储端却传出5.10GiB——多出来的,是整仓库快照,不是对话内容。

文档说的是一套,实测跑的是另一套

xAI 的企业部署文档反复强调本地会话存到 ~/.grok/,企业客户可以开 Zero Data Retention(ZDR),开了之后 prompt 和代码不在推理层持久化,还提供 grok sessions deletegrok memory clear 这样的清理命令。整套叙事的重点是“你的数据可控、可删、可本地化”。

但检索 xAI 全部公开文档,找不到任何一处提到 /v1/storage 接口或 grok-code-session-traces 这个存储桶。文档讲的是消费者能感知的那一层:本地文件夹、删除命令、隐私开关。实测抓到的,是文档完全没覆盖的另一层:一条默认开启、把整仓库连同 git 历史打包上传的后台通道。

  • 风险.这套机制在普通消费者账号(非企业 ZDR)下默认打开,用户没有对应的关闭入口。

更值得记一笔的细节是,把 /v1/settings 里“Improve the model”那个训练开关关掉之后,接口返回的 trace_upload_enabled 依然是 true。也就是说,那个用户以为能管住数据去向的开关,其实只管训练,不管上传。

三家 CLI,姿态不是一回事

同样是要读代码库的编程 CLI,几家公司在“默认要不要传整个仓库”这件事上的官方表态并不一样。OpenAI 的 Codex CLI 文档明确说默认只发 prompt、上下文摘要和可选的 diff,不整体上传源码;Anthropic 的 Claude Code 文档只说明使用需要联网做 AI processing,没有做“不整仓库上传”的明确承诺,消费级账号删除对话后 30 天内彻底清除,商业客户可申请 ZDR;Grok Build 这边,文档同样语焉不详,而实测证据直接指向“整仓库默认上传”。

三家CLI:默认是否整仓库上传 Codex CLI 官方明确承诺 只传prompt/摘要/diff 不整体上传源码 Claude Code 表述较模糊 联网AI processing 企业可申请ZDR Grok Build 文档空白 实测:整仓库默认上传 训练开关关不掉存储

这份证据链本身也有它没做到的地方,得说清楚:它证明了数据被“传输、接受、存储”,没有证明 xAI 拿这些数据去训练模型——训练与否是另一个问题,目前没有证据支持,也没有证据排除。研究者只在 macOS、0.2.93 这一个版本上测试,其他平台和版本是否一样,不知道。这套结果目前只有作者本人的抓包和 Reddit 上一条未经证实的复现讨论,xAI 官方还没有回应。

但“数据合规靠开关”这个默认心智,已经被这次测试戳穿了一角。孔子讲“听其言而观其行”,放在这里正合适:开关和文档是“言”,抓包抓到的字节数才是“行”。对拿真实代码库跑 Grok Build 的团队来说,眼下最现实的动作是:密钥文件不要留在被 CLI 扫到的目录里,或者干脆先等 xAI 把 /v1/storage 这套机制写进文档、给出关闭方式,再决定要不要把私有仓库交给它。

开关管的是训练,不管的是上传,这中间那道缝,才是真问题。

接下来该盯的,是 xAI 会不会正面回应这份抓包结果,会不会给消费级账号补一个真正能关掉整仓库上传的选项。在那之前,“已开启 ZDR”和“已关闭训练”都不等于“数据没有离开你的机器”。