Grok Build CLI向xAI发送的数据揭秘
速览
本文详细分析了xAI推出的Grok Build CLI工具在实际使用中向xAI服务器发送了哪些数据,包括构建信息、环境变量等。这些发现可能影响开发者对数据隐私和工具透明度的关注。文章对于理解AI开发工具的数据行为具有重要意义。
AI 深度解读
背景
xAI 推出的官方编码 CLI 工具 grok(Grok Build)旨在帮助开发者通过终端与 Grok 模型交互、编写代码。然而,一位安全研究人员对 grok 的实际网络行为进行了可复现的逆向拆解,发现该工具在默认情况下会向 xAI 的服务器上传大量数据,包括用户本地 .env 文件中的密钥(secrets),以及整个 Git 仓库的完整内容(含历史记录)。该拆解基于 macOS Apple Silicon 平台、grok 0.2.93 版本,通过 mitmproxy 代理捕获流量,并使用伪造的“金丝雀”密钥仓库进行验证,未暴露真实凭据。研究结果已发布在 Hacker News 上,引发了对隐私与数据安全的广泛讨论。
核心内容
xAI 的官方 Grok Build CLI(grok)在普通消费者登录后,会执行三个值得精确记录的动作:
-
传输所有读取的文件内容(包括
.env密钥文件)至 xAI,原样、无删节。该密钥出现在两个通道中:- 实时模型交互轮次:通过
POST /v1/responses发送。 - 会话状态(
session_state)归档:通过POST /v1/storage上传并被接受(HTTP 200),该端点对应的二进制路由指向grok-code-session-tracesGCS bucket(见原文 §5)。
- 实时模型交互轮次:通过
-
上传整个仓库——所有被跟踪文件的内容加上 Git 历史——独立于代理实际读取了什么。Grok 打包工作区并通过
POST /v1/storage上传。直接证明:在一个真实代码库中,使用提示词“回复 OK,不要读取任何文件”,Grok 仍然将整个仓库作为 Git bundle 上传(POST /v1/storage → 200);克隆捕获的 bundle 可以恢复一个代理被告知不要打开的文件——src/_probe/never_read_canary.txt——其唯一标记原样存在,连同完整的 Git 历史(见附录uploaded_repo.bundle)。该行为具有规模性:在一个 12 GB 的从未读取过的随机文件仓库中,/v1/storage传输了 5.10 GiB,全部返回 HTTP 200(中途被截断),而模型交互通道仅移动了 192 KB——比例约为 27,800 倍,明确将上传行为指向代码库本身,而非读取的内容。没有任何存储上传失败;唯一的非 200 状态码是模型使用配额(402/429)和一次无关的 404,而非存储大小限制。 -
存储目的地是 Google Cloud Storage 的
grok-code-session-traces存储桶(并非 AWS S3)——该名称以明文形式出现在二进制文件中以及捕获的metadata.json中(gs://grok-code-session-traces/…)。研究人员未在 CLI 的安装/快速入门材料中找到此机制(未做详尽文档审计,见原文 §7),该功能默认启用,且关闭“改进模型(Improve the model)”选项并不会禁用该上传(/v1/settings仍返回trace_upload_enabled: true;见原文 §6)。
以上所有发现均不证明 xAI 使用这些数据进行训练——这是一个策略问题(原文 §6 讨论)。但已证明的数据传输、接受和存储行为是确凿的。
安装与身份验证
- 安装:
curl -fsSL https://x.ai/cli/install.sh | bash→~/.grok/bin/grok - 认证:首次启动打开浏览器 → 登录 X / SuperGrok(消费者账户,非 API 密钥)
- 二进制身份(可复现):
~/.grok/bin/grok -> ../downloads/grok-macos-aarch64,Mach-O 64-bit 可执行文件 arm64,版本grok 0.2.93 (f00f96316d4b),SHA-256:2a97ba675bd992aa9b981e2e83776460d94f469b510c0b8efe28b50d236d767c
上传机制
上传机制是一个第一方 Rust crate。在二进制文件上运行 strings 得到以下源路径和常量(可复现):
crates/codegen/xai-data-collector/src/gcs.rs
crates/codegen/xai-data-collector/src/storage_client.rs
crates/codegen/xai-data-collector/src/queue.rs
crates/codegen/xai-data-collector/src/file_access_tracker.rs
crates/codegen/xai-data-collector/src/circuit_breaker_observer.rs
crates/codegen/xai-grok-shell/src/upload/{gcs,turn,trace,manifest}.rs
grok-code-session-traces
storage.googleapis.com
"Uploading bytes to GCS via proxy"
网络捕获方法
- 环境:macOS, Apple Silicon,
grok 0.2.93, 2026年7月(原文日期)。 - 安装 mitmproxy,生成 CA 证书,信任该证书。
- 通过代理运行 Grok:
HTTPS_PROXY=http://127.0.0.1:8080 SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem grok -p "<prompt>" --cwd <repo> - 使用 mitmdump 插件记录每个请求:方法、主机、路径、响应状态、请求字节大小;并保存 xAI 主机的请求体。
- 对于阶段性的工件检查,在运行期间竞速复制
~/.grok/upload_queue/*,然后gzip -dc | tar -xO。
金丝雀测试仓库
每个文件携带唯一标记,以便在捕获的流量中明确追踪。秘密文件 secrets.env / .env 内容:
API_KEY=CANARY7F3A9-SECRET-should-not-leave
DB_PASSWORD=CANARY7F3A9-DBPASS
声明:当 Grok 读取一个文件时,其内容会被传输至 xAI——序列化到 POST /v1/responses 模型交互体中,并打包到 session_state 归档中通过 POST /v1/storage 上传并被接受(HTTP 200)——文件内容未经任何删节。.env 文件像其他任何文件一样被发送。
有线工件:一个已解密的 48,070 字节的 POST cli-chat-proxy.grok.com/v1/responses 请求体(可通过嵌入的 "messages":[...]"model":"grok-4.5" JSON 识别为模型交互轮次)。其中包含完整的秘密文件内容(附录 secrets_responses_body.bin,secret_verbatim.txt):
…API_KEY=CANARY7F3A9-SECRET-should-not-leave\nDB_PASSWORD=CANARY7F3A9-DBPASS\n…"model":"grok-4.5"…
可复现:grep -a "CANARY7F3A9-DBPASS" secrets_responses_body.bin → 匹配。所有六个文件标记(源码、逻辑、README
