关了隐私开关也没用?Grok Build 0.2.93 整仓上传抓包实录与防泄漏指南
云端的 Coding Agent 要完成任务,几乎不可避免地需要将部分代码传出本地环境。这里真正的关键并不在于“是否联网”,而在于:离开本机的究竟是任务所需的上下文片段,还是整个代码仓库;控制开关约束的仅仅是数据能否用于模型训练,还是数据本身的传输行为。
独立研究者 cereblab 对 Grok Build CLI 0.2.93 版本进行了 Wire-level 级别的网络抓包分析。其结论边界非常明确:在消费者账号及当时的默认远程配置下,客户端会将已追踪(tracked)的仓库内容及其完整的 Git 历史记录打包为 Git Bundle,通过存储接口上传,并被服务端以 HTTP 200 状态码成功接收。这一事实与“Agent 是否实际读取了某个具体文件”是解耦的;同时,这与“上传的数据是否被用于模型训练”也是两个截然不同的命题。
本文旨在梳理该事件的证据边界和可复现的实验设计,并探讨如何将“退出模型训练”、“代码上传行为”、“服务端数据留存”以及“企业级零数据保留(ZDR)”这四个概念区分处理。由于软件行为会随客户端版本和远程配置的更新而发生变化,下文的讨论均严格限定在 0.2.93 版本及公开抓包材料所描述的条件范围内。
我们需要回答的核心问题
在讨论任何关于“整仓上传”的问题时,我们至少需要拆解出以下四个维度:
- 数据传输:代码数据是否离开了本地机器?是通过哪条接口被接收的?
- 影响范围:上传的内容仅仅是 Agent 阅读过的代码片段,还是整个被 Git 追踪的代码树及全部历史记录?
- 数据用途:这些数据是否会进入模型训练、产品改进流程,或者被用于其他未公开的用途?
- 数据留存:这些数据在服务端会以何种策略存储?存储多久?企业用户是否可以选择不持久化数据?
网络抓包能够很好地回答前两个问题。然而,后两个问题则更多依赖于厂商的隐私政策、账号权限层级及官方声明,无法单凭一次 HTTP 200 的请求响应直接得出结论。
现有证据的边界
根据公开的分析材料,其测试条件大致如下:
| 维度 | 条件 |
|---|---|
| 客户端 | Grok Build 0.2.93(分析给出的 macOS arm64 二进制 SHA-256:2a97ba675bd992aa9b981e2e83776460d94f469b510c0b8efe28b50d236d767c) |
| 账号 | 消费者登录 / SuperGrok;非企业 ZDR 团队 |
| 测试方法 | 本地 HTTPS 拦截(如 mitmproxy);未观察到该分析路径存在证书绑定(Certificate Pinning) |
| 工作区 | 专用的 Canary 测试仓库,内含虚假密钥与全局唯一标记文件 |
| 已证实的结论 | 数据已传输出境;存储请求已被服务端接受;从抓包获取的 Bundle 中可还原出未被读取的 Canary 文件与完整的 Git 提交历史 |
| 尚未证实的结论 | 数据是否被用于模型训练;是否存在人工访问;云端数据的最终删除时间线 |
本次事件的主要信息来源是 cereblab 发布的 Wire-level 分析报告 及其 复现仓库。随后,也有其他独立设备针对同版本客户端提供了旁证。本文旨在对这些公开证据进行结构化的解读,并提供一套基于空白测试仓库的验证流程,而非宣告一次全新的原始抓包发现。
剖析两条独立的数据路径
如果仅仅将“云端 Agent 需要获取代码”视为单一的数据通道,很容易掩盖其背后的风险结构。深入分析表明,实际上存在两条截然不同的数据路径。
路径 A:基于模型交互的上下文。
请求会进入大模型的推理接口(在公开材料中体现为 POST …/v1/responses)。Agent 主动打开的文件内容会被纳入模型的上下文。在测试中,被读取的 .env 等文件内的 Canary 虚假密钥以明文形式出现,并未观察到针对这类敏感内容的数据脱敏措施。
路径 B:基于仓库快照的后台上传。
请求会进入存储接口(在公开材料中体现为 POST …/v1/storage),分析指向的目的地是一个名为 grok-code-session-traces 的 GCS 存储桶。上传的载体是 Git Bundle,包含了所有被追踪的文件及其完整的提交历史。值得注意的是,即使用户在提示词中明确要求“只回复 OK,不要读取任何文件”,路径 B 的上传行为依然会发生;测试中从未被 Agent 打开过的 Canary 标记文件,依然可以从被拦截的 Bundle 中完整还原出来。
区分这两条路径至关重要。用户的指令或许能约束 Agent 的主动阅读行为,却不一定能限制客户端后台的仓库打包上传逻辑。系统弹出的权限提示、文件访问审批以及“不要读取”类的 Prompt,仅仅是对 模型行为 的约束;而如果整仓上传是由一条独立的后台管线自动完成的,那这就属于 客户端/框架层(Harness)行为。
数据传输的量级对比也为这一结论提供了有力的旁证。在一个体积约 12 GB、几乎全为 Agent 未读取过的随机文件的仓库中进行测试时,存储接口通道在被手动中止前,累计上传了约 5.1 GiB 的数据,且均收到 HTTP 200 响应;而同一时期,模型推理接口的数据流量仅约 192 KB。由于原报告明确指出上传行为是在进行中被主动截断的,我们不能说“12 GB 的仓库被全部传完”;但这足以证明:该管线产生的大规模流量与“模型实际读取的内容”严重不成比例,反而与代码仓库的总规模更加吻合。
使用空白测试仓库进行验证
在进行安全验证时,首选方案应是构建一个可随时丢弃的 Canary 测试仓库,切忌直接在生产环境的 Monorepo 中进行测试。
构造最小可证伪对象
mkdir /tmp/grok-build-canary && cd /tmp/grok-build-canary
git init
mkdir -p src/_probe
echo 'CANARY-NEVERREAD-UNIQUE-MARKER' > src/_probe/never_read_canary.txt
echo 'API_KEY=CANARY-FAKE-NOT-REAL' > secrets.env
git add .
git commit -m "canary: plant never-read marker"
# 额外两次提交,用于证明历史也被纳入 bundle
该设计的核心意图在于:
- Canary 标记文件必须被 Git 追踪(Tracked)。公开证据明确指出的上传范围是已追踪的内容及历史记录;至于
.gitignore中的文件是否被打包进 Bundle,在原材料中并未得到单独证实。 - 标记字符串必须具备全局唯一性,以便在抓包的请求体中精准检索。
- 密钥使用虚构的假值即可。此举的目的是验证传输路径的存在,而非人为制造真实的凭据泄露风险。
固定版本并拦截流量
grok --version
# 请确认版本为 0.2.93;若客户端已升级,前述报告的结论将不能直接外推。
在系统已信任抓包工具 CA 证书的网络环境下,执行如下命令:
HTTPS_PROXY=http://127.0.0.1:8080 \
SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem \
grok -p "Reply with exactly: OK. Do not read or open any files." \
--cwd /tmp/grok-build-canary
如何界定充分的证据
仅仅在“日志中发现 upload 字样”通常是不够的。更为严谨的判定标准应包含以下几点:
- 确实观察到了向存储接口发起的请求,并且服务端的响应状态码为 200;
- 抓取到的请求体数据能够被成功还原为 Git Bundle 文件;
- 对还原的 Bundle 执行
git clone操作后,能够发现未被要求读取的 Canary 标记文件依然完整存在其中; - 还原出的 Git 提交历史与本地测试仓库的多次提交记录完全一致。
如果仅满足第 1 点而无法满足第 3 点,最多只能说明存在可疑的大批量(Bulk)数据传输流量,尚不足以断言“未读取的文件内容已经被传输出境”。
此外,进行对照实验也非常有价值,例如:关闭“改进模型(Improve the model)”选项后重新测试;使用另一个全新的空白仓库进行验证;或者在客户端升级、等待数日后再进行复测。根据公开信息的描述,即便关闭了与训练相关的隐私选项,路径 B 的上传行为在最初依然会发生。但大约从 2026 年 7 月 13 日起,对同一版本客户端的复测显示,整仓上传至 Storage 接口的行为已经停止,且从服务端的配置响应中可以观察到类似 disable_codebase_upload: true 的字段。这表明,官方可以通过下发远程策略,在客户端不发版的情况下改变其默认行为,这本身也是现代软件安全模型的一部分。
厘清四个不同的控制面
在许多产品的设置界面中,“隐私”选项往往将多个不同的控制面折叠为了一个简单的开关。但在企业级部署和严谨的安全分析中,我们最好将它们逐一拆解。
1. 退出模型训练 (Opt-out of Training)
这一面控制的是:已经被收集或即将被收集的用户数据,是否被允许用于改进厂商的 AI 模型。
典型的设置入口包括“改进模型(Improve the model)”或“隐私对话(Private Chat)”等选项。选择退出训练,仅仅回答了“数据用途”的问题,它并不能自动等同于“数据不会离开本地机器”。在针对 0.2.93 版本的抓包测试中,单纯关闭该选项并不足以阻止路径 B 的整仓上传行为。
2. 代码数据上传
这一面控制的是:数据传输行为本身是否发生。
如前所述,路径 A 由 Agent 的主动阅读行为驱动,而路径 B 则是由后台的仓库快照管线驱动。对于包含敏感信息的代码仓库而言,这是首要关注的问题:数据的出境边界是否已经被越过。
3. 服务端数据留存
这一面控制的是:数据一旦传输出境后,在云端会以何种策略保留?保留多长时间?
根据 xAI 面向 API 用户的公开安全说明,其基本策略大致为:在普通情况下,用户的请求与响应数据最多可能被保留约 30 天(主要用于滥用审计等目的),随后将被删除。然而,CLI 端的会话轨迹(Trace)与整个代码库(Codebase)对象是否完全适用这一 30 天条款,还需要以官方最新的文档及具体的账号协议为准。抓包测试只能证明“数据的上传写入被服务端接受了”,它无法替代云端严格的数据删除审计流程。
此外,Grok Build CLI 中提供的 /privacy 命令,在官方的回应及社区的实测中,其功能更偏向于管理云端的 Coding 数据留存并触发已同步数据的删除,而非在客户端本地拦截数据发送的过滤器。
4. 企业级 ZDR (Zero Data Retention)
这一面控制的是:在签订了企业级合同及进行团队配置的前提下,模型推理路径是否能够做到完全不持久化存储用户的任何内容(零数据保留)。
官方的企业部署文档将 ZDR(Zero Data Retention)描述为一项团队级别的能力:一旦启用,Grok Build 的云端服务将走零留存路径;不过,用户本地的 ~/.grok/ 目录下仍可能保存有会话的历史记录。至于通过 API Key 调用的路径是否同样遵循 ZDR 策略,需以官方当前的具体说明为准。
需要强调的是,个人的 SuperGrok 订阅与企业的 ZDR 并非同一个控制面。个人订阅档位的提升,不能替代严苛的合同级别数据边界保障。
| 控制面 | 核心关注点 | 常见的用户误解 |
|---|---|---|
| 退出训练 | 数据能否被用于改进模型 | 误以为关闭后,代码数据就不会传输出境 |
| 代码上传 | 数据是否离开了本地机器 | 误以为只要 Agent 不主动读取,就不会上传 |
| 服务端留存 | 数据在云端最长保留多久 | 误将“最多保留 30 天”等同于“根本没有上传” |
| 企业 ZDR | 服务端是否实现真正的零持久化 | 误以为个人高级账号默认已享有 ZDR 保护 |
风险缓解与安全约束建议
建立可靠的安全控制,应当按照优先级将多种手段叠加使用:本地硬开关、运行环境策略、网络出口限制以及企业级配置。厂商下发的远程默认值只能作为当前的观察结果,决不能将其视为长期的安全保证。
1. 在本地配置中禁用整仓上传
# ~/.grok/config.toml
# 企业环境优先写入 /etc/grok/requirements.toml 并 pin 住配置
[harness]
disable_codebase_upload = true
社区的安全加固测试将这一配置项描述为整仓上传管线末端的“一票否决”。对于有严格合规要求的场景,建议将此配置写入 requirements.toml 这一更基础的层级,以防止其被普通的用户配置或下发的远程策略所覆盖。
2. 禁用会话轨迹与遥测数据采集
[features]
telemetry = false
[telemetry]
trace_upload = false
mixpanel_enabled = false
export GROK_TELEMETRY_ENABLED=0
export GROK_TELEMETRY_TRACE_UPLOAD=0
通常情况下,环境变量的优先级高于配置文件,但其仅对继承了该环境变量的调用路径有效。如果直接调用二进制可执行文件,可能会绕过 Shell 包装脚本(Wrapper)中设置的环境变量。此外,软件的自动更新可能会随时改变这些配置项的底层语义,因此在每次客户端大版本更新后,都应使用 Canary 仓库重新进行安全验证。
3. 建立对界面开关的正确预期
- 改进模型(Improve the model):主要涉及模型训练与产品改进,绝不能单独将其视为数据上传的拦截开关。
/privacy命令:主要用于管理云端的数据留存与删除;它很有用,但不应错误地假设它能关闭路径 B 的后台上传管线。
4. 加固网络与运行环境
官方的企业部署文档列出了模型推理与身份鉴权所需放行的主机域名。而本次事件分析中发现的 Bulk 大流量上传,还额外涉及到了对象存储域名(如 GCS)及特定的存储桶。因此,对于敏感的研发工作负载,更为稳妥的组合策略是:
- 实施严格的网络出口白名单,并配置针对异常大批量(Bulk)数据上传的监控告警;
- 仅在经过代码脱敏的副本、隔离的容器环境或用后即毁的虚拟机(Ephemeral Environment)中运行 Agent 工具;
- 确保生产环境的真实凭据和敏感密钥绝对不进入 Git 的工作树及提交历史。
5. 如果您已在敏感仓库上使用了 0.2.93 版本
您应当按照“被追踪的代码树及全部提交历史可能已经传输出境”的最坏情况来启动事件响应预案,而不是仅仅去调整几个配置开关:
- 全面盘点受影响的仓库、操作账号及时间窗口(需要特别注意在父级目录中误启动 Agent 的情况);
- 彻底扫描当前代码树及完整的 Git 历史记录,排查是否包含敏感密钥;
- 对于发现的凭据,遵循“先吊销,后轮换(Revoke then Rotate)”的安全原则;
- 密切审查云平台审计日志、Git 托管服务、私有包仓库以及 CI/CD 系统的近期异常使用记录;
- 通过官方正规渠道提交工单申请数据删除,并妥善保留工单记录及响应时间线以备查。
官方做出的“将会删除数据”的承诺,在您的团队完成独立的审计确认之前,只能视为一种积极的意向,不能作为风险闭环的最终证据。
核心时间线回顾与启示
- 0.2.93 版本抓包事件:证实了路径 B 可以悄无声息地打包并未被 Agent 实际读取过的 Canary 标记文件以及完整的代码历史;单纯在隐私设置中选择退出训练,不足以阻止该行为。
- 服务端策略收敛:在事件曝光后的复测中,同版本客户端的整仓 Storage 上传行为停止;同时观察到服务端远程配置下发了禁用整仓上传的控制信号。
- 官方沟通与澄清:官方明确表示企业级 ZDR 路径不会持久化用户的 Code/Trace 数据;对于消费者侧,则引导用户使用
/privacy命令来主动管理数据的留存与删除。 - 遗留的未闭合问题:已经上传到云端的历史代码对象,其彻底删除的完成情况仍待确认;默认开启整仓上传的产品动机及其潜在的影响面仍需讨论;未来如果厂商再次通过远程配置改变开关默认状态,用户端能否保持充分的可观测性?
厂商通过远程 Flag 确实可以快速地降低全局的默认安全风险。但只要客户端的代码中仍保留了这套打包上传的能力,企业真实的数据安全边界就依然取决于自身严密的本地策略部署与网络出口控制。
总结与安全原则
与其针对单一产品进行无休止的争论,不如将本次事件浓缩为几条可迁移、普适性的安全原则,这对于未来的技术选型和风险防范将更为有益:
第一,将框架(Harness)行为与模型(Model)行为分开建模。
Agent 大模型“主动阅读了什么”绝不等于底层客户端代码“打包上传了什么”。我们日常使用的 Prompt 约束、文件访问审批弹窗以及数据训练开关,往往只作用于模型交互这一层,而无法约束底层的框架行为。
第二,用 Canary 标记证明影响范围,用版本号钉死结论边界。
“全局唯一的标记文件 + 完整的 Git 历史 + 拦截到的网络 Bundle 包”,这种严密的证据链远比几张群聊截图和二手的转述更为坚实。同时,由于软件迭代极快,安全结论必须与具体的版本号牢牢绑定,一旦更换版本,所有结论必须推倒重测。
第三,隐私与安全控制应按“控制面”进行拆分理解。
模型训练、数据传输、云端留存、ZDR(零数据保留),这四者回答的是完全不同层面的安全问题。产品设计上把它们统合在一个“隐私设置”页面里,并不代表它们在底层架构中受同一个开关控制。
第四,强硬的环境隔离边界优先于概率性的主动监督。
当数据出境是由客户端后台管线默默完成时,用户的注意力与“不要读取敏感文件”的提示词指令都是极其不可靠的。更加坚实的安全约束来自于:提供最小化的工作副本、在本地配置文件中硬性禁用、严格限制网络出口流量,以及签署具备法律效力的企业级 ZDR 合同。
第五,当前工作区没有敏感信息,不等于 Git 历史是干净的。
完整 Git Bundle 被打包上传的风险不仅仅在于“你现在正在编写的源码”,更在于那些隐藏在提交历史中、自以为已经被删除的敏感密钥、早期客户标识以及未发布的商业逻辑。
结语
在针对 Grok Build 0.2.93 版本、消费者账号及当时默认远程配置的测试下,公开的抓包证据表明:该客户端有能力将整个被追踪的 Git 仓库打包为 Bundle 并上传至云端,其上传范围不仅覆盖了 Agent 未曾读取过的文件,还囊括了完整的 Git 提交历史。这一事实证明的是“客户端的数据传输与服务端的成功接收”,它与“数据是否被用于大模型训练”是两个独立的问题。
“退出模型训练”、“限制代码上传”、“30 天级别的云端普通数据留存”以及“企业级零数据保留(ZDR)”,是四个必须被清晰区分的独立控制面。对于个人开发者,建议至少在本地配置文件中启用 disable_codebase_upload,并在每次客户端升级后,使用空白的 Canary 测试仓进行复测;对于企业环境,则必须将配置文件锁定(Pin)、网络出口限制策略以及合同级别的 ZDR 协议结合起来统筹考量。
毋庸置疑,云端的 Coding Agent 必须获取代码才能发挥其强大的生产力。然而,厂商真正在产品中需要向用户清晰交代的,并不是含糊其辞的“是否允许访问此仓库”,而是应当明确告知:“客户端是否会复制整个仓库?以及复制上传之后,这些数据在云端究竟会被如何处理?”
参考资料
cereblab:Grok Build CLI wire-level 分析(0.2.93) ·
cereblab 复现仓库 ·
xAI Grok Build Enterprise 文档 ·
xAI API Security FAQ ·
The Hacker News 报道 ·
Hive Security 二次整理