夜雨聆风学习资料网

ARTICLE · 1042646

钥匙在谁手里,决定 AI 编程工具是备份还是收集

钥匙在谁手里,决定 AI 编程工具是备份还是收集

当工具开始替你"记住"一切,真正的问题是:谁手里握着那把钥匙。

一个程序员只是想清理一下硬盘。

他在 `~/.zcode` 目录里翻到一个 313MB 的加密文件,后缀是 `.enc`,躺在一个名叫 `pending` 的文件夹里。配套的状态文件没有加密,他打开一看,里面记着:这个包来自他手头一个正在做的商业项目,已经尝试上传 564 次,全部失败,还在排队等下一次重试。

真正让他后背发凉的是另一件事:这个 313MB 的加密包,他自己解不开,ZCode 客户端也解不开。全世界只有一家公司的服务器能打开它。

这是 9 月 18 日技术博主 ferstar 发在个人博客上的逆向取证,对象是智谱旗下的 AI 编程桌面软件 ZCode。当天文章在开发者社区传开,傍晚智谱发布情况说明并道歉。我把那份七分钟读完的取证报告和官方公告并排读了一遍,发现大多数报道都漏掉了真正值得警惕的部分——这件事和"黑客拖库"是两回事,严重程度也远不止"默认开了个开关"。

先把定性说准:没有外部攻击者

事件发酵后,很多标题用了"偷传代码""数据泄露"。情绪可以理解,但写之前得把事实分三层摆清楚。

开发者取证到的:ferstar 称,只要 ZCode 处于登录状态,客户端就会在后台把整个工作区打包、加密,直传阿里云对象存储(OSS),且界面上没有开关能真正关闭。他给出了本地文件、状态元数据、反编译后的上传代码和网络连接作为证据链。

智谱官方承认的:9 月 18 日的说明把问题归因于"代码库索引"功能,称 Repo Wiki 在云端生成知识库页面时"可能触发仓库数据上传",页面生成后数据"立即销毁、不会保存";该功能上线初期默认开启,部分用户未充分感知,目前已修复;同时承诺近期开源 ZCode 代码库、引入第三方评估审查,并给全体用户补偿一次周额度重置。

双方说法仍有出入的:截至 9 月 19 日的公开报道,智谱没有逐项说明上传范围是否包含完整 Git 历史、那 564 次重试的数据最终去了哪里,"立即销毁"也无法从用户这一端验证。

所以更准确的定性是:目前没有证据表明有外部攻击者把数据偷走、流向黑产;争议的核心是在用户没有充分知情、也无法阻止的情况下,工具默认把多少东西搬上了云。这两件事的严重程度不一样,混为一谈反而不利于讨论。

一个"本地索引",为什么要把整座仓库搬上云

要理解开发者为什么愤怒,得先看清这条数据流水线长什么样。ferstar 拆开了 ZCode 的客户端安装包(Electron 应用的 `app.asar`),把上传流程还原了出来,大致分三步。

第一步,客户端向智谱的协调服务 `zcode.z.ai` 申请一组凭证,服务端返回阿里云 OSS 的表单签名、一个动态的存储对象名、大小上限,以及这一轮加密用的 RSA 公钥

第二步,客户端在本地把工作区打成 tar.gz 压缩包,用一次性对称密钥(AES-256-CTR)加密,再用服务端给的 RSA 公钥把这把对称密钥包起来。

第三步,客户端绕过智谱自己的应用服务器,用一个 HTTP 表单把加密包直接 POST 到阿里云 OSS,再由 OSS 回调智谱后端登记。他检查运行中的网络连接,能看到 ZCode 进程一直连着 `zcode.z.ai` 和两个阿里云 OSS 节点。

最有信息量的是加密设计。这是一套教科书式的"信封加密",内容用对称密钥加密、对称密钥再用 RSA 包裹。关键在那把 RSA 公钥:它由服务端临时下发,对应的私钥从不下发到用户电脑。ferstar 用本机所有私钥尝试解包,全部失败。

这意味着什么?你硬盘上那份 313MB 的密文,你打不开,软件也打不开,只有智谱后端能打开。ferstar 给了一个很锋利的判断标准:如果这个功能真是为了让你做本地回滚、跨设备同步,那解密钥匙应该在你手里,就像 Git、就像 macOS 的时间机器;一把只有服务器握着的钥匙,它服务的对象就不是你。

一条登录即启动、开关拦不住、钥匙只在服务端的直传管线。

被传走的 86.6%,是这个项目的"完整人生"

加密包本身打不开,但打包时生成的文件清单(Manifest)是明文存在本地的,于是他给出了一份精确清单:一个 42,411 个文件的快照里,装的是下面这些东西。

内容
体积
占比
`.git/lfs/`(LFS 大文件缓存)
196.1 MB
56.8%
`.git/objects/`(完整提交历史对象库)
102.2 MB
29.6%
`.git/logs/`(本地分支操作轨迹)
0.6 MB
0.2%
源码与文档
约 46.2 MB
13.4%

按他的统计,光是 `.git` 目录就占了整个载荷的 86.6%,你当前正在编辑的源码反而只有一成多。

这个比例是整件事最关键的数字。因为 `.git` 文件夹不是"你现在的代码长什么样",而是这个仓库从创建第一天到今天的完整谱系:后来某次提交里已经删掉的历史 API 密钥和数据库配置,仍然躺在历史对象里;你还没推送的本地分支名,会暴露尚未发布的功能规划;`.git/config` 里写着的内网 GitLab 主机名和仓库路径,等于递出去一张内网地图。取证中这个仓库总大小约 10GB,排除依赖后打包了约 345MB,按作者的说法"几乎全是核心知识产权"。

你以为传走的是眼前的代码,被打包的却是整个项目的来龙去脉。

另有一份附加清单,会把用户的全局 ZCode 配置(比如 `settings.behavior.json`)做哈希后,跨项目塞进每一次快照。

需要说明的是,上述文件构成来自 ferstar 的单方逆向,智谱尚未公开确认这个范围。但它解释了为什么"只传了一点点、用完就删"的说法很难让开发者安心:如果传的真是当前任务需要的那几个文件,犯不上把几年的提交历史也带走。

两个开关,为什么都拦不住它

发现被上传,普通人的第一反应是去设置里关掉它。ferstar 把界面开关和反编译出的代码逐一对照,结果不太妙。

一个叫"优化体验"的开关(`optimizeAgentExperienceEnabled`),用户以为能关掉数据收集,代码里它只决定数据是否被授权用于模型训练,快照的捕获和上传照常进行。另一个叫"仓库快照索引"的开关(`repoSnapshotIndexingEnabled`),听起来像快照总闸,但它只管服务端要不要给已上传的快照建索引,本地该打包还是打包、该传还是传。

他在宿主进程代码里看到,负责捕获和上传的组件在启动时被无条件创建,没有任何基于用户偏好的判断分支,只要"你登录着、能拿到有效令牌"它就运行。捕获时机有两个:每次你发一条指令之前,以及任务完成时;一个活跃会话的日志里最多出现过 62 次捕获。他还做了个实验:手动删掉待传的包,半小时内客户端重新打了一个新的,失败计数从 564 跳到 565——删除是在打地鼠。

社区里另一层担忧来自权限设计。有技术分析指出,这条外传管线跑在宿主层,不在 AI Agent 的工具列表里:你给 Agent 配的所有"调用工具前先问我""禁止访问某些目录",对这条旁路都不生效。等于你仔细审了 AI 的手,却没审装着 AI 的那个壳。这部分属于第三方的独立梳理,同样有待智谱和后续审计回应。

另有用户晒出火绒流量监控截图,称该进程后台上传量达 43GB;这个数字来自用户截图和媒体转述,我无法独立核实,只能作为"可能存在更大传输量"的线索,不能当成定论。

判断任何一个 AI 编程工具,先问四个"默认值"

类似的事并非只此一起。今年 7 月,xAI 的 Grok Build 也被曝默认上传完整 Git 历史,甚至有用户称自己的 SSH 私钥、密码库落在上传路径里。这类事件密集出现,其实给了普通开发者一套可以复用的排查框架。我把它归纳成四个"默认值",换任何工具都能照着问。

第一,默认开还是默认关。 数据收集、用于训练,是默认替你打开、需要你主动退出(opt-out),还是默认关闭、需要你明确授权(opt-in)?这一个默认值,基本决定了大多数懒得改设置的人会被如何对待。

第二,传的是上下文,还是整座仓库。 模型推理确实需要读取相关代码,这是使用 AI 编程工具的合理代价。要警惕的是越过"当前任务相关文件",把整个工作区、完整 Git 历史、全局配置一起打包。

第三,开关是真门控还是装饰。 设置页给你一个开关,不代表它在代码里真的拦住了上传。能不能在网络层验证(监控出站连接)、厂商愿不愿意公开说明开关对应的具体行为,是试金石。

第四,钥匙在谁手里、删没删能不能验证。 备份功能的解密钥匙应该在用户本地;如果密钥只在厂商服务器、留存多久不透明、"用完即删"你无法验证,那它和可审计的备份就是两回事。能不能本地部署、有没有零留存(zero retention)条款,是更彻底的选项。

拿这四条横向看主流工具,差异其实写在公开文档里(以下为截至 2026 年的公开口径,具体以各家官方条款为准):

工具
代码是否上云推理
默认是否用于训练
更稳的隐私选项
Cursor
是,发送相关上下文
免费/专业版隐私模式默认关闭,需手动开
开启隐私模式后不存储、不训练;企业版强制
GitHub Copilot
2026 年 4 月起免费/专业档默认用于训练,可退出
商业/企业版合同承诺不用于训练
Windsurf
免费档可能用于训练
付费可开零数据留存,团队版默认开启
Claude Code
提供零留存选项
ZCode
被指登录即整仓加密快照
官方称训练授权可关
智谱承诺开源并引入第三方审计,待落地

摆这张表不为比烂,只想讲清一件事:"用 AI 就要把代码交出去"是个伪命题,真正的分野在于交出去多少、你能不能控制、钥匙在谁手里。

下次再装新工具,别急着点"同意",先把这四个问题问一遍。

如果你在用,现在能做什么

对普通开发者,我给几个按成本从低到高的动作。

先自查:看看本地 `~/.zcode/v2/checkpoints/`(Windows 在用户目录的 `.zcode\v2\checkpoints`)有没有异常体积的 `.enc` 文件和 `pending` 队列;用系统自带的网络监控或火绒、Little Snitch 这类工具,看编程工具在你不主动使用时有没有持续对外上传;翻一遍隐私设置里每一个开关,别只看开关名字,去官方文档或更新日志确认它实际控制什么。

敏感仓库(含商业密钥、未公开代码、客户数据)在审计结论出来前,最稳妥的是不要让这类工具直接接触,或者放进隔离环境/容器里使用;公司层面则应把"登录态下的出站连接清单、落盘文件及可读性、开关的代码级验证、隐私政策与实际行为比对"写进采购审计——这次的教训是,行为和文档对不上时,按行为算。

ferstar 还给了一个技术上更激进的办法:在文件系统层把 checkpoints 目录锁死(macOS 用 `chflags uchg`,Linux 用 `chattr +i`),让捕获进程无法落盘,上传管线自然无米下锅;代价是"检查点回滚/时间线"功能失效,但正常聊天、补全和工具调用不受影响。Windows 没有等价的简单命令,需要用 NTFS 拒绝权限,操作前务必先在测试目录验证。这些命令有一定门槛,不熟的话不要在主力环境直接动手。

信任的单位,正在从"承诺"变成"可验证"

事件发生后,智谱的回应速度不算慢:当天道歉、承认默认开启的问题、称已修复、承诺开源代码库和第三方审计、还给了补偿。方向是对的——尤其是开源和第三方审计,这恰恰是把"我说我没存"变成"你可以自己查"最可靠的出路。

但开发者这次没有轻易买账,也在情理之中。一句"立即销毁、不会保存",在私钥只存在于服务端、上传范围没说清、开关被验证拦不住的前提下,是一个用户无法证伪也无法证实的承诺。信任这种东西,建立的时候靠的是可验证的默认值,耗掉的时候往往只需要一个打不开的黑盒。

我不想把一家公司一棍子打死。AI 编程工具确实在实实在在提升效率,智谱也愿意走到开源这一步。真正值得记住的是那个简单的判断:钥匙在你手里,它替你备份;钥匙只在它手里,它就在收集。 这句话不只适用于 ZCode,也适用于未来每一个会伸进你代码库的 AI。

相关学习资料