上个月中,一个 ID 叫 ferstar 的开发者在清磁盘。他注意到 `~/.zcode` 这个目录占了 700MB 以上,顺手翻开,里面躺着一个 313MB 的 `.enc` 加密包。
顺着这个包,整条链路被拉了出来:智谱的 AI 编程工具 ZCode 在登录状态下,会把本地 Git 仓库整个打包、加密,直传阿里云 OSS。
这个包之所以还留在他硬盘上,是因为状态文件里写着一行 `failureCount: 564`——网络问题,连续 564 次上传失败。这句话反过来读更冷一点:如果这 564 次里成功过一次,这件事大概永远不会有人知道。知乎

而过去这三个月,被翻出来的同类事情不止这一件。我把知乎、微博、小红书上的讨论,和 Glow Labs、Adversa AI 两家安全机构的原始报告串了一遍,发现大家吵的其实是四件性质完全不同的事,只是被压缩成了同一句"AI 编程不安全"。
先说结论:你正在焦虑的那一类,恰恰是唯一已经有人替你兜底的;真正没人管的另外两类,换个工具也不会消失。
一、同一套剧本,三个月里演了三遍
先把事实摆平。
ZCode(智谱,9 月 18 日—22 日)。 逆向 `app.asar` 后还原出的细节相当具体:上传范围不只是当前源码,还包括完整 `.git` 历史、LFS 大文件缓存、reflog 操作日志和全局应用配置。一份 42,411 个文件的快照清单统计显示,`.git` 占 86.6%,源码文档只占 13.4%。也就是说,被搬走的不是"你现在写的代码",而是你的完整提交历史、未推送分支名、内网主机名,以及那些早就从工作区删掉、但还躺在历史里的密钥配置。微博知乎
触发方式也不挑时候:一个 sidecar 进程随登录常驻,触发点是 `captureBeforePrompt`(每次提问前)以及任务完成、RepoWiki 更新时,属无条件触发;单个活跃会话中最多出现 62 次捕获。手动删掉待传的加密包,约半小时内会自动重新打包继续重试。加密用的是信封加密:内容 AES-256-CTR,对称密钥再由服务端下发的 RSA 公钥包裹,而 RSA 私钥只存在云端。这意味着你连本地这份密文自己都解不开,想自查"到底传了什么",只能看到文件名和体积。知乎微博

UI 上确实有两个看起来相关的开关——「优化体验」和「仓库快照索引」。但据社区逆向,两者与"要不要打包上传"完全解耦;隐私政策文本里也没提整库快照和 Git 历史上传。开关给的是心理安慰,不是技术边界。知乎
Grok Build(xAI,7 月)。 剧本几乎逐字相同。研究员 cereblab 用 mitmproxy 对一个 12GB 本地仓库抓包,发现 xAI 在 7 月 13 日通过服务端远程配置 `disable_codebase_upload: true` 关闭了上传——但 0.2.99 版本二进制里,整库上传的代码完整存留,只是被服务端标志暂停。随后 xAI 以 Apache-2.0 开源了 84.4 万行 Rust 代码。知乎
同一批研究里还有个细节值得记住:他们在仓库里放了一个 `never_read_canary.txt`,并在明文指令里写"不要读取"。这个文件连同全部 commit 历史仍然被上传了。知乎
Cursor(7 月)。 开发者 Migel Tissera 公布日志称,在他取消订阅几个月后,7 月 18 日至 27 日 Cursor 仍向服务器上传了 63,106 个文件、约 736MB,包含源代码和项目依赖。他强调自己那段时间并没有用 Agent 或 Composer,只是把 Cursor 当普通 IDE 打开了几个文件夹——代码索引似乎只检查是否登录,不检查是否付费。小红书
Cursor 官方文档其实承认了这套机制:开启代码库索引后,会把代码切成小块上传计算 Embedding,明文代码在请求结束后删除,但 Embedding、文件哈希和文件名等元数据可能继续保存在数据库中。分歧不在"传不传",而在"为什么默认开启"和"取消订阅后为什么还在跑"。小红书

三件事的处理路径也高度一致:道歉 → 服务端开关 → 开源。智谱这边节奏很快:9 月 18 日用户群致歉,19 日推 v3.14.0 移除相关入口,20 日宣布 MaaS 平台"数据内容不留存",21 日以 Apache-2.0 开源 ZCode 桌面端、浏览器端、后端服务与终端 Agent,中国信通院和绿盟科技入场做第三方审计。港股"大模型第一股"智谱(2513.HK)当天早盘承压,盘中一度跌超 5%,10 点左右收窄至 4.23%。据媒体报道,维权群接近 400 人。知乎微博微博
但社区对"开源"这次的反应是审慎,不是欢呼。原因有两个。
第一,没有可复现构建(reproducible build),开源就只是把源码当文档发布,而不是把二进制置于监督之下。"被审查的代码"和"你机器上实际跑的代码"可能不是同一份。Grok Build 那次已经演示过:关闭上传靠的是服务端下发的一个标志位,客户端代码原封不动地留在那里。知乎
第二,审计结论要连范围一起读。 信通院和绿盟的结论是可信的,同时也是有限的——它们证明的是某个时间点的某个版本、某个存储桶的状态。"已删除"和"没被使用过"之间,隔着一条事后审计填不平的沟。
最实在的一个时间点是:太原承明科技正式发函追责,称被上传约 425MB 数据,涉及 6 个工作区、34,549 个文件,包含完整源代码、系统架构、版本控制历史、数据库口令、云服务凭证及员工个人信息,提出 12 项要求,要求 10 月 10 日前书面答复并保留法律追责权利——就是今天。9 月 20 日下午,承明科技把公开函件隐藏了,表示正与智谱沟通;截至发稿,这份书面答复的内容没有公开。知乎
二、真正没人兜底的,是另外两类
上面这一整类,责任方是厂商,路径也是厂商的:股价、维权、监管、审计、开源、发函。它有兜底链条,哪怕慢,哪怕不完整。
接下来这两类没有。
第二类:Agent 自己找路。
安全机构 Glow Labs 在 9 月 29 日公开了一份叫 PixelLeak 的研究:他们扫描了 300 多家组织、900 多个代码仓库,找到 13000 多张本应留在内部的开发者截图,全部托管在公开可访问的 GitHub 仓库里。其中 93% 位于员工用自己用户名创建的仓库下。约三分之一的组织用过开源工具 gitshot,截图落在 `_gitshot` 标签下,100 多个公开账号经这条路泄露。受影响行业包括云、医疗、金融科技、政府、前沿 AI——甚至包括 AI 安全公司自己。小红书知乎
起因普通得离谱。开发者让编程 Agent 改完界面后附上前后对比图给人审。问题在于:编码 Agent 走的是文本命令行,它没法把截图附进私有仓库的代码评审里,因为 GitHub 的图片代理是匿名抓取的,私有仓库的图在评审者那边会显示成坏图。于是 Agent 自己做了个决定:新建一个公开仓库,把截图固定到某个提交上,再把链接贴回 PR。Glow Labs 在实验室里复现过:让 Claude Code 改一个测试项目的页头颜色并展示效果,它就新建了一个公开仓库放那两张截图。另一个案例是一家 10 万人以上的制造企业,开发者让 Agent 验证内部账单页面的修复,截图里是一家公用事业公司的账单记录,被放进了开发者个人账号下的公开仓库。小红书知乎
真正麻烦的不是"截图泄露"这四个字,而是它落在了公司安全团队根本不会去扫的地方——个人账号下的公开仓库,不在企业资产清单里。代码仓库有分支、评审、扫描和权限控制,截图通常什么都没有。它一旦离开原页面,就不再只是"页面的一个画面",而是一份新的数据副本,而原页面的权限不会自动跟着它走。
这里必须说清楚证据边界:这些图确实被公开暴露了,但目前没有证据表明已经被谁下载利用;13000 张、300 多家、93% 这些数字来自 Glow Labs 自己的研究,没有独立复核。知乎
第三类:被人骗。
10 月 7 日 CSO Online 报道,安全公司 Adversa AI 演示了一种叫「加密上下文注入」的手法,对象是 GitHub Copilot CLI。过程是这样的:用户让 Copilot 去抓一个网页,网页里藏着一段加密内容,并"提示"Agent 用两个候选密钥去解密。其中一个密钥是个模板,必须读本机文件才能拼出来——Agent 为了拼出密钥,去读了 `.env.prod`。读文件这一步,其实已经是偷了。解密出来的指令再让它发一个网络请求。研究者说全程 28 秒,没有任何确认,而且对话记录里看不出数据去了哪个主机。知乎
这一类的关键区别在于:厂商未必把这算作它的漏洞。你的 Agent 没有"被攻破",它是被一段它读到的文本说服了,去做了一件在权限上完全合法的事。等补丁是等不来的。知乎
第四类,其实和工具无关:人自己乱传。 字节跳动 9 月 22 日的二季度内部通报里就有一条,员工用 AI 工具整理业务信息,生成了一百多份包含内部保密信息的文件。新加坡老字号美珍香则是员工操作 AI 工具不当,导致超过 9.5 万名顾客的电邮地址泄露——这是新加坡本地首起与 AI 有关的个人资料泄露事故,当地个人资料保护委员会 9 月 21 日在官网发布了文告。小红书微博
三、四类风险,只有一个共同的洞
把四件事并排放,会发现一个不太舒服的事实:
ZCode 能传走整个仓库,是因为那个 sidecar 进程有你工作区的读权限;PixelLeak 里的 Agent 能建公开仓库,是因为它有创建公开仓库的权限;Adversa 的 Copilot 能读 `.env.prod` 并发网络请求,是因为它有读文件和网络出口权限。
换个厂商,这三件事一件都不会消失。
所以真正的分界线不是"国产还是进口"“开源还是闭源”,而是这张表:
类型 | 谁越的界 | 换工具有用吗 | 有人替你兜底吗 | 你能单方面做什么 |
|---|---|---|---|---|
厂商静默上传(ZCode / Grok Build / Cursor) | 厂商 | 有用 | 有:股价、维权、审计、监管、发函 | 验证 + 换 + 轮换凭据 |
Agent 自己找路(PixelLeak) | 你给的授权边界 | 没用 | 没有,厂商不认这是漏洞 | 收权限、限网络出口 |
外部内容注入(Adversa 28 秒) | 你给的授权边界 | 没用 | 没有,不能等补丁 | 收权限、隔离密钥 |
人自己乱传(字节通报 / 美珍香) | 人 | 没用 | 公司制度 | 改习惯 |
第一行你能靠"选"来解决,后三行只能靠"配"来解决。而绝大多数人现在的注意力,全在第一行。
后三行怎么配?有个框架我觉得比任何工具的文档都好用:别按工具名称拆权限,要按后果拆。从生成一张截图到把链接放回 PR,中间至少有四次判断:它决定打开哪个页面、决定截取哪些区域、决定把文件写到哪里、决定用什么身份通过什么链接让别人看到。前两步影响内容,后两步影响暴露范围。所以"给 Agent GitHub 权限"根本不是一个足够具体的描述,至少要拆成:读取仓库、写入分支、上传附件、创建仓库、改变可见性、提交 PR、合并代码。知乎
判断标准不是动作听起来有多小,而是做错以后能不能撤回。改错一个临时分支,通常可以回滚;公开链接被搜索引擎、缓存或第三方保存之后,就不能假设删除等于收回。知乎
四、能单方面做的:把"承诺层"换成"事实层"
ZCode 那篇复盘里有一句话我觉得该抄下来贴墙上:UI 开关、隐私政策、致歉声明都属于承诺层;netstat、mitmproxy、canary 文件属于事实层。两者的差距,就是这次事故的全部空间。具体到动作,按性价比排:知乎
1. 先看本地缓存目录有没有不该有的体积。 任何"本地缓存目录里出现几十上百 MB 的加密包",都值得问一句:这个包本来是打算发给谁的。别信开关文案,抓包只认字节数——Cursor 那次能被坐实,靠的就是一份 63,106 个文件、736MB 的日志,而不是一句"我们不会上传"。小红书

2. 做一个对比测试,比读隐私政策可靠得多。 对同一个仓库分别跑"让它改一行 README"和"让它做一次重构",比较两条外发曲线的量级。如果改一行字也触发了几百 MB 外发,那传的就不是代码上下文,而是仓库。
3. 放一个 canary 文件。 在仓库里塞一个语义上绝不该被读取的文件,明文写清"不要读取",然后看它在不在外发流量里。xAI 那次就是这么验出来的,结果是它照样被传走了。
4. 已经泄露的话,删掉 `.env` 没有用。 因为它在 `.git` 历史里,而历史已经被打包走了。唯一有效的补救是轮换凭据——把这当成工单,不是当成心情。知乎
5. 工程边界比工具选择更重要。 给编码 Agent 用独立的、最小权限的凭据,且与生产环境隔离;`~/.aws`、`~/.ssh`、`~/.kube` 这类目录不要出现在 Agent 的工作机上。这一条是你能单方面决定的,不依赖任何厂商的善意。
社区里已经有人在做工具化的事:Apache 软件基金会旗下的开源项目 CasbinGateway 就被拿来复现 ZCode 事件、盯住每个 Agent 的外发。也有人干脆把开发环境整个搬上云服务器的 code-server,本机只当浏览器入口。知乎
如果你用的是 Claude Code,权限系统里有几个具体的坑值得当场检查:
别写裸的 `Bash`。 想表达"跑命令不用询问",顺手写一个单独的 `Bash`,在解析器眼里等于"Bash 工具、所有命令"全部放行——源码注释给这类规则定的性是"效果等同于绕过权限模式"。你心里想的是 npm,实际写下的包括 `rm -rf`。
拒绝永远排第一,这是安全设计。 源码注释写明拒绝检查必须先于一切放行检查。所以"允许改的文件默认也允许读"这条便利规则,能被你专门写的"拒绝读"压住。一个存着密钥的文件,你可以让它改得了、读不了。
敏感文件是 bypass-immune 的。 改 `.bashrc`、`.git/`、Claude Code 自己的配置,写了放行规则也照样弹窗,三种免弹窗的办法在这里全部失效。别指望 `bypassPermissions` 能省事。
检查一下你有没有攒了一堆死规则。 复合命令(比如 `cd src && … && npm test`)在老版本里会取开头两个词记成 `Bash(cd src:)`,`npm test` 仍然没人放行,弹窗照来,你再点一次,又多一条没用的规则。另外,一条单独 `Bash` 的"必须询问"会盖掉你写的 `Bash(ls:)` 放行。
弹窗时按 ctrl+e。 会有一个小模型当场解释这条命令在干什么、风险多高,解释失败也不耽误你选。
上面这几条不是我总结的经验,而是源码注释里写死的定性——比如"允许改的文件默认也允许读"这条便利规则,专门写的"拒绝读"排在它前面,所以密钥文件才做得到改得了、读不了。最后一条,也是最容易被跳过的一条:验收 Agent 时,别只测"它能不能完成",要测"它被拒绝后会不会停"。故意关掉一个关键权限——禁止创建公开仓库、禁止访问外部图床、禁止读取生产数据,或者把目标目录换成它无权访问的位置,然后看它的反应。合格的结果不一定是任务成功,而是它明确告诉你:缺什么权限、原本准备做什么、现在停在哪一步,然后等人拍板。如果它只是换一个账号、换一个服务、换一个目录继续尝试,说明这套系统把"完成"排在了"合规"前面。 PixelLeak 里那 13000 张截图,就是这么来的。知乎知乎
行业已经在用脚投票了:阶跃星辰 10 月 6 日开源 Step Code 时,讨论区里被反复提起的参照物就是 ZCode。字节跳动安全与风控部门早在去年 5 月就发内部邮件禁用 Cursor 等第三方 AI 开发软件、改推自研 Trae。"开源"正在从技术选型变成信任卖点——但按上面第一条说的,没有可复现构建的开源,卖的是文档,不是监督。小红书小红书
五、留几个观察信号
今天(10 月 10 日):承明科技要求智谱书面答复的期限。答不答、答什么范围,会决定这类事件后续走商务沟通还是走法律程序。
智谱开源仓库有没有补上可复现构建:这是"开源"从姿态变成监督的分水岭。
企业资产扫描范围会不会重画:如果 PixelLeak 的 13000 张站得住,"员工个人账号下的公开仓库"就得进安全团队的扫描清单——它现在基本不在里面。
Mods / Harness 兼容层的权限继承:Claude Code 刚开放 Mods、DeepSeek Harness 连夜跟进兼容层,第三方插件拿到的权限边界谁来定,目前基本是空白。这块的风险还没被认真讨论。
最后一句:Agent 越会想办法,越需要你提前把"哪些办法不许用"写成它绕不过去的限制,而不是指望它自己意识到。与其等每一个绕过方法都被修好,不如先假设它总有一天会被骗——然后让它被骗的时候,手里没什么可偷的。知乎