安全研究者发现智谱AI的ZCode桌面应用将用户整个代码仓库(含全部历史)打包加密上传云存储,未做任何告知。
如果你使用 AI 编程助手,你已经接受了它能看到你当前任务中的代码。但你大概不会想到,这个应用会把你的整个仓库——包括你曾经做过的每一次提交——打包后上传到云存储,而且全程不询问你。
这正是安全研究员 ferstar 记录下的事实,对象是智谱旗下的 AI 编程桌面应用 ZCode。完整报告于 2026 年 9 月 18 日发布,智谱同日确认了上传行为。本文将梳理此次调查发现了什么、这些细节为何重要,以及面对类似行为你可以怎么做。
以下所有事实均来自 blog.ferstar.org 的原始报告及智谱的公开回应。
研究员注意到 ~/.zcode 数据目录已经膨胀到 700MB 以上。其中有一个文件格外显眼:checkpoints 文件夹里有一个 313MB 的加密 .enc 归档,旁边是一个小小的状态文件:
{
"workspacePath": "/Users/ferstar/myprojects/<a commercial project>",
"lastCompressedSize": {
"encryptedSizeBytes": 313070842,
"workspaceSizeBytes": 345549173
},
"kind": "baseline",
"failureCount": 564
}
含义是:客户端扫描了一个活跃的商业项目,将 345MB 的内容压缩成 313MB 的加密归档,标记为 baseline(全量快照),且已经尝试上传了 564 次。该项目总计 10GB,排除依赖后,快照中几乎所有内容都是核心知识产权。
在这个案例里,这个大归档最终没有成功传出去——因为体积太大,一直上传失败。但另一个更小的仓库(来自一个公开仓库的 538 个文件)被压缩到约 15KB,状态显示为 accepted by the server(已被服务器接收)。所以至少有一个快照确实到达了云端。
应用日志里没有上传 URL,于是研究员解压了 Electron 客户端的 app.asar 包并阅读了代码。还原后的流程如下:
客户端调用 zcode.z.ai 上的 POST /api/v1/snapshot/upload-credential。服务器返回 OSS 表单凭证、大小限制以及一个 RSA 公钥。
客户端将工作区打包成 tar.gz 归档,使用 AES-256-CTR 加密,再用 RSA-OAEP-SHA256 和那个公钥通过 RSA-OAEP 方式用对称密钥包装对称密钥。
客户端通过 HTTP POST 表单将加密归档直接上传到阿里云 OSS。流量从不经过智谱自己的应用服务器。
OSS 触发回调,让后端记录上传完成。
实时的网络检查印证了这一图景:运行中的进程保持着到 zcode.z.ai 以及两个阿里云 OSS 节点的持久连接。
这是标准的信封加密,而问题恰恰就在这里。
文件内容使用随机对称密钥通过 AES-256-CTR 加密。
那个对称密钥使用服务器在上传时提供的公钥,通过 RSA-OAEP-SHA256 进行包装。
私钥只存在于云端。研究员用本机上的所有私钥尝试解密那个信封,全部失败。你自己磁盘上的 313MB 密文,既无法被你打开,ZCode 客户端也打不开,只有智谱的后端持有那把密钥。
如果目标是为了崩溃恢复或跨设备同步来让你受益,解密密钥应该存在于你的机器上,就像 Git 或 Time Machine 的数据那样。只有服务器能打开的密钥,只有一个用途:确保服务器能读取所有内容。
加密载荷无法读取,但快照清单以明文形式存储在本地。研究员统计了一份涵盖 42,411 个文件的清单:
.git/lfs/:196.1MB,56.8%(历史上通过 LFS 拉取的每一个大型二进制资产).git/objects/:102.2MB,29.6%(完整的提交、树和 blob 历史).git/logs/:0.6MB,0.2%(reflog,包括未推送的本地分支活动).git 目录单独就占了快照的 86.6%。如果那个归档到达云端,接收方得到的远不止你当前的 Working Files:
.git/config,通常包含内部 GitLab 主机名和仓库路径此外,代码里还有一个 repo_snapshot_extra_manifest,会对你的全局 ZCode 配置文件做哈希,并将它随快照一起打包到每个工作区中。
自然的反应是打开设置把开关关掉。研究员将每个开关对应到代码,发现没有一个能触及上传行为:
在客户端代码中,快照边车(snapshot sidecar)在启动时无条件实例化,没有针对用户配置的检查。唯一的要求是一个有效的登录令牌。一旦登录,每次发送提示词之前都会进行捕获,一个活跃会话最多产生了 62 次快照捕获。
9 月 18 日,报告扩散数小时后,智谱发布了一份声明,后被 IT之家等媒体报道。其要点如下:
公司不否认上传发生过。但从外部无法验证的有:
最新版客户端 3.14.0 已从物理上移除了上传管道,凭证端点现在返回 404。3.12.3 版,即调查中捕获的版本,拥有完整的上传管道。
删除待处理的归档没有用。半小时内客户端就会生成一个新的 313MB 快照,失败计数器从 564 变成 565。上传器检测到文件缺失后直接重新打包。手动删除是打地鼠。
可靠的修复是在文件系统层面设置不可变锁,让内核直接拒绝写入快照目录。
rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
chflags uchg ~/.zcode/v2/checkpoints
# Verify: this should fail with Operation not permitted
touch ~/.zcode/v2/checkpoints/test
rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
sudo chattr +i ~/.zcode/v2/checkpoints
# Verify: this should fail with Operation not permitted
touch ~/.zcode/v2/checkpoints/test
这样做带来的代价:检查点回滚和时间线功能将停止工作,而这些功能本来就是用完整代码上传换来的。正常补全、聊天和工具调用不受影响。要撤销锁定,在 macOS 上对目录运行 chflags nouchg,在 Linux 上运行 sudo chattr -i。
研究员在修复后仍然保持这个锁定,因为具有热更新能力的客户端随时可能恢复上传管道。它充当一个警报器:如果突然发现对该目录的写入成功了,说明什么东西变了。
这个模式比单个应用更大。任何接触你源代码的工具都值得问三个问题:
什么东西会离开你的机器? 任务范围的上下文是可以预期的。包含完整历史的全量仓库快照是完全不同的一回事。
谁持有密钥? 如果供应商加密了数据但把唯一的解密密钥留在他们自己的云端,那加密保护的是他们,而不是你。
你真的能关掉它吗? 一个控制训练数据的开关,而管道本身却无条件运行,这不是真正的同意开关。
在将商业仓库托付给一个工具之前,审计它上传了什么。检查其数据目录是否有意外增长,观察它的网络连接,当供应商声明数据被"立即销毁"时,记住你没有办法验证。红线得自己画,而文件系统锁有时是唯一真正生效的开关。
某些评论可能仅对登录访客可见。登录以查看所有评论。
如需进一步行动,你可以考虑屏蔽此人或举报滥用。