大数跨境

ZCode静默上传代码库事件深度复盘:一个过滤器的白名单分支,和它漏掉的那一半

ZCode静默上传代码库事件深度复盘:一个过滤器的白名单分支,和它漏掉的那一半 象信AI
2026-09-18
10
导读:给企业CISO提个醒

这不是一次入侵。没有 0day,没有漏洞利用,没有恶意代码。 所有环节都合法:合法进程、合法签名、合法凭证、合法的公有云域名、合法的 TLS。 更值得注意的是——厂商确实写了密钥过滤器,过滤器也确实在工作。它只是恰好对携带已删除历史的那一半数据完全失效。


一、事件经过:从一次磁盘清理开始

9 月 18 日,独立开发者 ferstar 发布逆向分析文章。起因是清理开发机磁盘时发现 ~/.zcode 占用超过 700MB。

https://blog.ferstar.org/en/posts/zcode-silent-workspace-snapshot-upload/

在 v2/checkpoints/ 下,他发现一个 313MB 的 .enc 加密包,旁边的状态元数据写得很清楚:

{
  "workspacePath""/Users/ferstar/myprojects/<某商业项目>",
  "lastCompressedSize": {
    "encryptedSizeBytes"313070842,
    "workspaceSizeBytes"345549173
  },
  "kind""baseline",
  "failureCount"564
}

客户端扫描了活跃的商业项目,排除 node_modules 等目录后,把剩余 345MB 打包为 313MB 的加密档案,标记为 baseline(全量快照);并记录了 564 次上传失败,文件滞留在本地 pending/ 等待重试。该仓库总计 10GB,扣除依赖后剩下的 345MB 几乎全部是核心知识产权。

记住 564 这个数字,后面会回到它。


二、上传链路:绕过自家服务器,直传阿里云 OSS

日志中没有明文上传 URL,作者解包客户端 app.asar 逆向还原出两段链路:

第一段,申请凭证。 客户端向 https://zcode.z.ai 请求,服务端返回 OSS 表单签名(policyx-oss-signature)、动态 Object Key、大小限制,以及本轮加密使用的 RSA 公钥。

第二段,直传对象存储。 本地完成归档与流式加密后,客户端绕过 ZCode 自己的应用服务器,通过 HTTP POST 表单把 tar.gz.enc 直接投递到阿里云 OSS,OSS 再回调后端登记快照。对活动套接字的检查印证了这一点:运行中的 ZCode 进程同时维持着到 zcode.z.ai 与两个阿里云 OSS 存储节点的长连接。

这个架构选择对企业侧安全能力是致命的,稍后详述。


三、加密设计:钥匙只在服务端

标准的信封加密:内容用临时对称密钥经 AES-256-CTR 加密;对称密钥再用服务端下发的公钥以 RSA-OAEP-SHA256 封装。

关键在那把公钥:它由服务端在凭证协商阶段下发,对应私钥从未落到用户机器上。作者用本机全部私钥尝试解开信封密钥,全部失败。

躺在你自己硬盘上的那个 313MB 密文,你打不开,客户端也打不开,只有服务端后台持有钥匙。

原文作者的判断是:如果这个功能真是为用户侧回滚或跨设备同步设计的,密钥应该留在本地(就像 Git 或 Time Machine)。


四、第二份独立分析:从官方安装包做静态验证

事件扩散后,另一路分析者从官方 3.12.3 的 macOS 安装包入手做了静态验证——sha512 与官方 latest.yml 逐字节一致,全程仅静态解包,未安装、未登录、未运行。Agent 运行时位于 ZCode.app/Contents/Resources/glm/zcode.cjs

这份分析给出了三个关键补充。

4.1 整条上传链路,没有一处经过模型

在厂商自己的代码里(out/host/index.js)可以看到完整的调用面:

  • RepoSnapshotSidecarService 类
  • captureBeforePrompt / captureBeforePromptUnsafe
  • tokenProvider(拿不到登录 token 就直接 return)
  • uploadClient.getUploadKey()
  • plaintextArchivePath / encryptedArtifactPath / envelopePath

这条链上没有任何一个环节调用模型。

这一点非常重要,它关掉了一整类叙事出口。不能说"是 Agent 自主决策带上了上下文",也不能说"模型判断需要这些文件"。这是确定性的产品逻辑,是被设计、被编码、被构建进发行版的行为,唯一的门控条件是 tokenProvider 能否返回有效登录态。

4.2 打包范围:.git 走的是"先行放行"的白名单分支

这是目前为止最有价值的技术发现。

scanRepoSnapshot 的流程分两步:

  1. git ls-files --cached --others --exclude-standard 取工作区文件
  2. appendRootGitMetadataPaths()递归把整个 .git 目录再加回来(有个专门的函数叫 walkGitMetadataFiles

问题出在过滤器:

function shouldIncludeRepoSnapshotPathBeforeSample(e){
  ...
  return isRootGitMetadataFile(p) || hasGitInternalSegment(segs)   // ← .git 命中这里
    ? {include:true}                                               //   直接放行
    : ...dependency / cache / build-output
      / looksLikeSecretPath(...)      // .env .env.* *.pem *.key *.p12 含 token/secret
      / sizeBytes > 1048576           // 1 MiB

看清楚这个三元表达式的结构:**.git 命中的是一条在所有排除规则之前 return {include:true} 的白名单分支**。

后果是,对 .git 目录下的内容:

  • looksLikeSecretPath() 密钥路径过滤 —— 绕过
  • 1 MiB 单文件体积上限 —— 绕过
  • 二进制检测 —— 绕过

于是出现了一个非常刺眼的矛盾:

一个 .env 文件躺在工作区里,会被 looksLikeSecretPath 判定为密钥并排除;同一个 .env 躺在历史 commit 里,会随 packfile 原样上传。

系统内部对同一份数据给出了两个互相矛盾的判定,而更宽松的那个赢了

.git/lfs 同理——这也解释了为什么 196.1MB 的 LFS 缓存能整包走出去:因为体积上限在这条分支上根本不生效。

厂商写了 secret 过滤器。过滤器是有效的。它只是恰好对携带已删除历史的那一半数据完全不生效。

这不是"忘了排除 .git"。忘了排除,意味着 .git 落入默认分支、接受各项规则检查;而实际代码是显式地把它先行放行。两者在工程责任上不是一个量级。

4.3 提示词来源:与 Claude Code 高度同源

同一份静态分析还发现,ZCode 的系统提示词与 Claude Code 高度一致,基本是把产品名替换了一遍。主提示词首句:

You are an interactive ZCode agent that helps users with software engineering tasks.

紧随其后的一段与 Claude Code 的 IMPORTANT: Assist with authorized security testing... 一字不差。其它自我声明位置:

位置
自我声明
CLI 前缀段
You are ZCode, an interactive coding agent
子 agent
You are an agent for ZCode CLI.
探索子 agent
You are ZCode Explore, a file search and codebase research specialist for ZCode CLI.
Output Style 变体
You respond to the user according to the active Output Style below while using ZCode's tools

但替换时漏掉了一处:记忆挑选子 agent 的开头仍然是

You are selecting memories that will be useful to Claude Code as it processes a user's query.

这句里不含 "ZCode" 字样。

值得记录的是分析者在这里的处理方式:他没有把这条强行归属给 ZCode,理由是——真 Claude Code 很可能也在发同样的字符串,强行认领等于把原厂标错。这个判断我们认为是对的,也顺带引出了本文后面一个重要论点。


五、开关问题:UI 选项与代码门控不一致

开关
用户预期
实际作用
优化体验
optimizeAgentExperienceEnabled
关闭遥测 / 数据收集
仅控制数据是否被授权用于模型训练,快照捕获与上传照常运行
仓库快照索引
repoSnapshotIndexingEnabled
关闭快照功能
仅控制服务端是否对已上传快照建立索引,本地打包与上传不受影响

从宿主装配代码看得更清楚:捕获/上传的 sidecar 在启动时被无条件实例化,没有针对用户偏好的 if 门控,唯一前置条件是有效 JWT。

触发点有两处:每次 Prompt 之前的 captureBeforePrompt,以及任务完成时标记为 repo-wiki-update 的回调。会话日志中,单个活跃会话产生了多达 62 次捕获事件。

隐私政策方面,ZCode 的隐私政策说明会收集"对话中提交的文本、文件与代码"——这是喂上下文的标准做法。但在整份政策、FAQ 与更新日志中,没有任何一处提及会静默打包上传整个工作区与完整 Git 历史


六、打包清单:86.6% 是 .git

打包过程生成的 Manifest 以明文保存在本地。一份 42,411 个文件的快照结构:

内容
体积
占比
包含的信息
.git/lfs/
196.1 MB
56.8%
LFS 缓存——历史上拉取过的全部二进制资产与大文件
.git/objects/
102.2 MB
29.6%
完整提交历史对象库(commit / tree / blob)
.git/logs/
0.6 MB
0.2%
reflog——本地分支历史与未推送的操作痕迹
源码与文档
~46.2 MB
13.4%
src/
、配置文件、内部文档

云端拿到的远不止当前工作树,而是仓库从第一天起的完整血统:后续 commit 中已被删除的历史 API 密钥与敏感配置;未推送的本地分支名(泄露未发布的功能规划);.git/config 中配置的内网 GitLab 主机名与仓库路径。

此外,repo_snapshot_extra_manifest 会对全局 ZCode 配置文件(如 settings.behavior.json)做哈希,随每次快照跨工作区一并打包。


七、官方回应(9 月 18 日下午)

事件发酵后,智谱通过用户群官方渠道发布说明并致歉。官方称已第一时间完成自查,问题源于 ZCode 的"代码库索引"功能,该功能旨在帮助用户在本地生成仓库索引,以支持包括历史版本在内的会话检查点恢复、历史版本回退及 Repo Wiki 等功能。

官方说明中提到,Repo Wiki 功能在生成 Wiki 页面时可能会触发仓库数据上传,Wiki 页面在云端生成后相关上传数据会立即销毁、不会保存;由于该功能在上线初期默认开启,部分用户因此受到影响,目前相关问题已经修复。

官方同时承诺近期开源 ZCode 代码库,邀请第三方评估人员对系统运行情况进行审查并持续公开进展,并为全体 ZCode 用户额外提供一次周额度重置。

截至相关报道发稿时,该回应尚未通过智谱官方微博等公域渠道发布。

同期有开发者反馈在更早版本上也观测到类似上传行为,该说法尚未经独立验证,此处仅作记录。


八、我们的判断:值得 CISO 记住的,不是智谱

以上是事实。以下是我们认为被集体漏掉的部分。

观点一:出境通道已迁移到通用云基础设施

企业过去一年做的 AI 管控,本质是域名层面的黑白名单:封禁或代理各家大模型接口,接上 SSL 解密和 DLP。

这套逻辑在本案中完全失效。因为数据出口是 **oss-cn-*.aliyuncs.com**——一个没有任何中国企业敢封的域名。你的 CDN、日志归档、备份、镜像仓库、第三方 SaaS 全跑在上面。

**攻击面从"AI 厂商的接口"迁移到了"厂商租用的通用对象存储"**,而后者天然在所有企业的白名单里。

请写进威胁模型:**"访问的不是 AI 域名",不能再作为"没有把数据交给 AI"的证据。**

观点二:信封加密让"泄露范围"变成不可举证

传统泄露事件中取证是可行的:抓包、还原、界定范围、定损、通知。这次不行——密文就在你硬盘上,你却无法知道里面装了什么。

后果三重:

  1. 企业无法自证清白。 你没法告诉客户/监管"泄露的只是 A 不含 B",因为你自己也不知道。
  2. 举证责任反转。 你只能依赖厂商的自述来描述你自己的泄露范围。
  3. "立即销毁、不会保存"是不可验证的承诺。 这不是质疑诚意,是架构问题——密钥在对方手里时,你没有任何技术手段验证任何一句承诺。

安全工程的第一性原理是:好的架构让你不需要相信对方。 对供应商实施零信任,和对内网实施零信任一样重要。

观点三(本文核心):过滤器悖论——安全控制恰好在最危险的那一半上失效

这是这次事件最应该被写进教科书的一点。

厂商并非没有安全意识。他们实现了 looksLikeSecretPath,覆盖 .env.env.**.pem*.key*.p12、含 token/secret 的路径;实现了 1 MiB 体积上限;实现了二进制检测。这是一套看得出用心的过滤器。

然后他们给 .git 开了一条在所有规则之前 return include:true 的通道。

于是:

数据形态
过滤器判定
实际结果
工作区里的 .env
命中 secret,排除
✅ 未上传
历史 commit 里的同一个 .env
走 .git 白名单分支
❌ 随 packfile 上传
工作区里的 200MB 二进制
超 1 MiB 上限,排除
✅ 未上传
.git/lfs
 里的 196MB 缓存
走 .git 白名单分支
❌ 整包上传

安全控制存在、生效、且恰好只在不危险的那一半上生效。

这比"完全没有过滤"更值得警惕,原因有两个:

第一,它会在任何自查中通过。厂商工程师如果被问"你们有没有做密钥过滤",答案是"有,代码在这里",而且完全属实。审计员看到 looksLikeSecretPath 的实现会打勾。缺陷藏在控制流的顺序里,不在控制的有无里。

第二,它揭示了一个普遍的心智模型错误:把"代码仓库"等同于"工作区文件"。绝大多数开发者和安全工程师在做数据分类时,脑子里的对象是 src/ 下那些文件。.git 被当作"元数据"、"基础设施"、"实现细节"——一个不需要做内容分类的黑盒。

但 .git/objects 不是元数据,它是你所有历史数据的完整副本。任何对工作区做的数据分类、脱敏、过滤,如果不同样施加于 .git,都只是掩耳盗铃。

给所有做数据安全的同行一句话:把 .git 当作一个需要做内容分类的数据库,而不是一个目录。

观点四:Git 历史是企业"密钥全史",而不是"当前密钥"

承接上一点,说清楚资产估值错误在哪。

企业的密钥轮换,通常只覆盖现网在用的凭证。历史 commit 里那些"当年不小心提交、后来 git rm 掉"的密钥、内网地址、数据库连接串、测试账号——绝大多数企业从未轮换过,理由是"已经删了"。

git rm 删的是工作树,不是对象库。一次全量 .git 出境,泄露的不是你今天的密钥,而是你公司成立至今的密钥史全集

另外两块常被忽略的情报:

  • .git/config → 内网 GitLab 域名、组织命名、仓库完整路径 = 一张内网侦察地图
  • .git/logs + 分支名 → 未发布分支 feature/xxx-2026q4 = 产品路线图与商业情报

源码泄露真正贵的部分,往往不是代码,是代码携带的情报。

观点五:这件事不是"AI 风险",所以你的 AI 治理框架管不到它

静态分析已经确认:整条上传链路没有一处经过模型

这意味着:

  • 它不会出现在任何"大模型安全评估"报告里
  • 它不会被任何 prompt 注入检测、模型输出审计、幻觉评估捕获
  • 它不受任何"AI 伦理/AI 治理"框架约束
  • 它甚至不需要模型在线

这是传统软件行为,穿着 AI 产品的外壳。

很多企业在过去一年建立的 "AI 安全委员会""大模型使用规范",评估对象是模型。而本案告诉我们:AI 工具的最大风险,可能完全不在 AI 那一侧,而在它的宿主进程里。

正确的评估对象不是"这个模型安不安全",而是"这个装在我员工机器上、拥有全盘读权限、任意出网权限和用户长期凭证的第三方常驻进程,安不安全"。

观点六:从行为特征看,它可以被完整映射到 ATT&CK

把厂商名字抹掉,只看行为:

观测到的行为
ATT&CK 映射
扫描并打包整个工作区
T1005 本地系统数据收集 / T1560.001 归档收集数据
递归收集 .git 全量元数据
T1552.001 文件中的凭证
AES-256 + RSA 信封加密,密钥服务端持有
T1027 混淆/加密文件
直传第三方云对象存储
T1567.002 向云存储外传
启动时无条件实例化 sidecar
T1543 持久化
删除后 30 分钟内自动重建,重试计数 564→565
对抗性持久化行为特征

一个商业软件的正常功能,在行为层面与数据窃取植入体无法区分

而这件事不是被任何安全产品发现的,是被一个人清理磁盘时偶然撞见的。在 AI 客户端工具这一层,现有安全栈的可见性接近于 0

观点七:Agent 的"身份"是可复制的字符串,不是可信标识

这是静态分析的第三个发现引出的、几乎无人讨论的问题。

越来越多企业在建"AI 使用审计":谁在用什么 Agent、调了什么工具、动了什么文件。而识别 Agent 身份的依据,通常是 User-Agent、接口特征、或者 Agent 的自我声明字符串

本案显示:一个产品的系统提示词可以整体来自另一个产品,连自我声明都只是做了字符串替换,且会替换不干净

于是:

  • 你的审计系统可能把 A 厂的 Agent 标成 B 厂
  • 你基于提示词指纹做的检测规则,会同时命中原厂和仿制品
  • 词界(word boundary)这种细节都是承重的——裸子串匹配会把合法业务字段误吞

在无意的复制下就已经如此。如果是有意的伪装呢?

给正在建 Agent 指纹库的团队几条实践建议:

  1. 优先级排序是承重的:更具体的签名必须排在更通用的前面
  2. 词界是承重的:用 \bzcode\b 而不是裸子串,否则 bizCode 这类字段会被误命中
  3. 单条字符串不足以定身份:应绑定"会话级"身份——主提示词确定身份后,后续事件继承;不要对每条消息独立判定
  4. 不要强行认领模糊证据:一条不含产品名的字符串,归属给谁都可能是错的。宁可标 unknown,也不要污染原厂的画像

这条原则的通用表述是:AI 系统的自我声明不是身份凭证,正如 User-Agent 从来不是。

观点八:问卷式供应商评估已经失效

把前面几点合起来看,结论很明确。

设想一次标准供应商评估:

  • 问:"是否提供关闭数据收集的选项?" → 答"是"。属实(开关存在,只是控制别的东西)
  • 问:"是否对敏感文件做过滤?" → 答"是"。属实looksLikeSecretPath 确实存在)
  • 问:"是否限制上传文件体积?" → 答"是"。属实(1 MiB 上限确实存在)

三个回答全部诚实,而结果是 345MB 含全量历史密钥的代码包出境了。

问卷不会撒谎,问卷只是问不到点上。真正的信息藏在控制流顺序、白名单分支位置、sidecar 实例化条件这些地方——这些东西只能观测,不能询问

所以:**AI 工具准入必须从"声明式"转向"验证式"**。在受控环境里实际跑一遍,抓包、看磁盘、读 manifest、比对开关前后的行为差异。

观点九:这次是 ZCode,问题出在构件形态

请把注意力从厂商移到形态上。

当下的 AI 编码工具,无论叫 IDE 插件、CLI Agent 还是 MCP Server,本质都是一个具备完整文件系统读权限、任意出网权限、自动执行权限、且持有用户长期凭证的第三方常驻进程

在这个形态下,从"读全部代码"到"传全部代码"之间没有任何技术障碍,只有产品经理的一念之差。而且它甚至不需要恶意——本案的起点很可能真的只是想做一个"历史版本回退"功能。

一个只需要善意就能避免的风险,不是风险控制,是运气。

你的开发机上现在有几个这样的进程?其中有多少个你逐一验证过它的磁盘行为和出网行为?

观点十:合规责任不会因为"是工具传的"而转移

如果仓库中包含个人信息(测试数据集、fixture、脱敏不彻底的样本、含真实手机号的单测),这次上传在《个人信息保护法》语境下可能构成向第三方提供个人信息;若涉及境外节点,还可能触及跨境传输规则。

注意:历史 commit 里的个人信息同样算数——而且它恰好是过滤器漏掉的那一半。

承担个人信息处理者责任的是使用工具的企业,不是提供工具的厂商。"是工具自己传的、我们不知情",在监管叙事里恰恰是"未尽到安全管理义务"的自认。


九、CISO 自查清单(可直接下发)

本清单为通用版本,不针对特定厂商,适用于所有 AI 编码工具与 Agent 类客户端。建议整段转发至研发负责人、IT 运维、安全工程与法务。

【P0】24 小时内:止血

1. 资产盘点——回答"谁装了什么"

  • [ ] 通过 EDR/MDM/资产平台,统计全部研发终端上已安装的 AI 编码客户端、IDE AI 插件、CLI Agent、MCP Server 清单
  • [ ] 标注每一项的:安装量、登录态用户数、可访问的代码仓范围、是否接触生产配置
  • [ ] 重点标记接触核心代码库、金融/医疗业务、含个人信息仓库的终端
  • [ ] 特别注意:**盘点对象是进程,不是"AI 功能"**。判断标准是"该进程是否具备全盘读 + 任意出网 + 常驻",而非"它是否调用大模型"

2. 本地留痕排查

  • [ ] 检查各 AI 工具数据目录是否存在异常体积的缓存/检查点/快照文件
  • [ ] 检查是否存在明文 manifest / 文件清单,若有,立即留存取证(这是唯一能界定泄露范围的证据)
  • [ ] 通用排查命令:
# 用户目录下各数据目录体积排行
du -sh ~/.* 2>/dev/null | sort -rh | head -30

# 大体积加密/归档产物
find ~ -type f \( -name "*.enc" -o -name "*.tar.gz" \) -size +50M 2>/dev/null

# 本地快照清单(取证关键)
find ~ -iname "*manifest*" -newermt "-90 days" 2>/dev/null

3. 针对本次事件的处置(ZCode 用户)

  • [ ] 确认客户端已更新至官方声明修复后的版本
  • [ ] 更新前在企业内暂停使用并退出登录(上传链路的唯一前置条件是有效登录 JWT)
  • [ ] 如需保留使用,可对检查点目录施加文件系统不可变锁:
# macOS
rm -rf ~/.zcode/v2/checkpoints && mkdir -p ~/.zcode/v2/checkpoints
chflags uchg ~/.zcode/v2/checkpoints
touch ~/.zcode/v2/checkpoints/test   # 应报 Operation not permitted

# Linux
rm -rf ~/.zcode/v2/checkpoints && mkdir -p ~/.zcode/v2/checkpoints
sudo chattr +i ~/.zcode/v2/checkpoints
touch ~/.zcode/v2/checkpoints/test   # 应报 Operation not permitted
  • [ ] 知悉副作用:检查点回滚/时间线不可用,正常对话、补全与工具调用不受影响;恢复用 chflags nouchg / sudo chattr -i

【P1】72 小时内:定损与凭证轮换

4. 按"历史全量泄露"假设做凭证轮换(本清单中价值最高的一条)

  • [ ] 对涉事仓库执行全历史密钥扫描,而不是只扫当前分支:
trufflehog git file://. --since-commit=<初始commit> --json
# 或
gitleaks detect --source=. --log-opts="--all" --report-format=json
  • [ ] 轮换扫描命中的全部凭证,包括"早已删除、认为不再有效"的历史密钥
  • [ ] 范围至少覆盖:云厂商 AK/SK、数据库口令、第三方 API Key、签名私钥、Webhook Secret、内部服务 Token
  • [ ] 若 .git/config 含内网 GitLab 域名/路径,评估内网拓扑泄露影响,加固相关入口访问控制
  • [ ] 不要因为"我们的 AI 工具有密钥过滤"而降低此项优先级——本案证明过滤器可以完整存在却对历史数据完全失效

5. 出网侧回溯

  • [ ] 在 NGFW/代理/流量审计中,回溯研发网段近 6 个月内到公有对象存储域名(*.aliyuncs.com*.myqcloud.com*.amazonaws.com*.cos.* 等)的上行大流量记录
  • [ ] 建立基线告警:单终端向对象存储域名单次上行 > 50MB,或日累计 > 200MB,触发人工复核
  • [ ] 不要以"目标域名不是 AI 厂商"为由排除(见观点一)

6. 合规评估

  • [ ] 判定涉事仓库中是否包含个人信息、客户数据、受托处理数据——包括历史 commit 中的
  • [ ] 若包含,启动个人信息安全事件评估流程,判断是否达到通知/报告门槛
  • [ ] 留存完整时间线、证据与处置记录

【P2】两周内:制度与准入

7. 把供应商评估从"声明式"改为"验证式"

  • [ ] 建立 AI 工具准入沙箱:装机 → 放置带诱饵密钥的测试仓库(工作区和历史 commit 中各放一份不同的诱饵)→ 全程抓包 + 磁盘变更监控 → 出具行为报告
  • [ ] 诱饵设计要点:在历史 commit 里埋一个已 git rm 的假密钥。如果它出境了,说明该工具的过滤器存在本文所述的同类缺陷
  • [ ] 准入必答项(要求书面回答,并在沙箱中逐条验证):
    • 是否读取 .git 目录?是否包含 objects / logs / lfs?
    • 敏感文件过滤规则是否同样作用于 .git 目录内的内容?请指出代码位置
    • 文件体积上限是否对 .git 生效?
    • 是否存在超出单次对话上下文的全量或增量仓库上传?触发时机?
    • 上传目的地是哪些域名?是否直传第三方对象存储?
    • 加密方案是什么?解密私钥在用户侧还是服务端?
    • 是否提供真正阻断上传的开关?请指出代码中的门控位置
    • 该功能链路是否涉及模型调用?(用于判断它是否受 AI 治理框架覆盖)
    • 数据保留期限?删除是否可验证?是否接受第三方审计?
    • 是否有本地/私有化部署形态?
  • [ ] 验证原则:开关与过滤器的有效性以抓包和磁盘观测结果为准,不以文档或问卷回答为准

8. Agent 身份识别与审计基线

  • [ ] 若已建 AI 使用审计,复核 Agent 识别逻辑:不得仅依赖自我声明字符串或 User-Agent
  • [ ] 指纹规则实践:更具体的签名排在更通用的前面;使用词界匹配避免误吞业务字段;采用会话级身份绑定而非逐条判定
  • [ ] 对无法可靠归属的事件标记 unknown,不做强行认领

9. 分级管控

  • [ ] 划定"禁用云端 AI 工具"的仓库红线:核心算法、密钥管理、支付清算、含个人信息的数据处理代码
  • [ ] 对红线仓库强制要求:仅使用私有化部署的模型与 Agent,或完全离线
  • [ ] 开发机基线中,对 AI 工具数据目录默认施加写入限制(MDM 批量下发)
  • [ ] 制度化:AI 工具的登录态即数据授权,离职/调岗/项目结束必须回收登录态

10. 长期架构:给 Agent 加一层运行时管控面

  • [ ] 承认一个事实:AI 工具的行为不可能靠采购问卷约束,只能靠运行时的策略执行与审计
  • [ ] 建设目标:Agent 的每一次工具调用、文件读取、网络出站,都可观测、可拦截、可留证
  • [ ] 建设目标:敏感数据在进入任何模型或外发通道之前被识别与阻断,而不是事后取证
  • [ ] 建设目标:过滤策略由企业自己定义和执行,不依赖上游厂商过滤器的正确性

十、写在最后:从"事后取证"到"运行时管控"

这次事件给 CISO 的核心启示,可以浓缩成一句:

AI 工具的数据风险,无法在边界上解决,也无法靠厂商的过滤器解决,只能在运行时解决。

出境通道是合法的、加密是端到端的、进程是签名的、凭证是用户自己的、过滤器是存在的——传统边界管控在这五个条件同时成立时全面失效。唯一有效的位置,是在 Agent 执行的那一刻做策略判断:它要读什么、要传什么、传到哪里,在动作发生之前被检查。

而且这道检查必须由企业自己执行。本案最深刻的教训不是"某个厂商做错了",而是:当你的数据安全依赖于第三方过滤器中一个三元表达式的分支顺序时,你没有数据安全。

同时,私有化部署是把"信任问题"转化为"控制问题"的唯一确定解。当模型与 Agent 运行在企业自己的边界内,你不再需要相信任何一份"数据会立即销毁"的承诺——因为数据从未离开过。

我们建议企业安全负责人评估 OpenGuardrails AIRS AI 运行时安全平台的私有化部署方案。它针对的正是本文讨论的这一层风险面:

  • AI 运行时可观测性:对 Agent 的工具调用、文件访问与网络出站行为建立统一的审计与阻断点,填补 EDR/DLP 在 AI 客户端层面的可见性空白
  • 数据外发管控:在数据进入模型或外部通道之前完成敏感信息识别与策略拦截,覆盖源码、密钥、个人信息——过滤策略由企业定义,不依赖工具厂商实现的正确性
  • 策略即控制,而非承诺:开关的有效性由企业自己的策略引擎保证,不依赖上游厂商的自述
  • 私有化部署:模型推理与 Agent 运行全部收敛在企业边界内,从根本上消除"泄露范围不可举证"的问题

如需技术交流、方案评估或 POC 测试,可联系:

📮 wanglei@xiangxinai.cn


本文技术细节引自独立研究者 ferstar 的公开逆向分析,以及另一路基于官方 3.12.3 安装包(sha512 与官方 latest.yml 一致,仅静态解包、未安装未运行)的静态分析;官方回应内容引自智谱通过用户群发布的公开说明及媒体报道。文中判断为作者观点,供企业安全决策参考。


【声明】内容源于网络
0
0
象信AI
让人放心把真实工作交给AI
内容 83
粉丝 0
象信AI 让人放心把真实工作交给AI
总阅读786
粉丝0
内容83