惊!ZCode 悄上传整个 Git 历史,加密密钥归服务器,界面设置无法阻止!

深入探究 ZCode:悄无声息地将你的整个 Git 历史上传至云端

2026 年 9 月 18 日 · 阅读约需 7 分钟

目录

  • 起始点:一个 313MB 的存档文件处于待处理状态
  • 去向追踪:从日志到 asar 文件逆向工程
  • 最具讽刺意味的部分:加密密钥归服务器所有
  • 打包内容分析:近 90% 是 .git 目录
  • 开关真相:界面设置无法阻止上传
  • 隐私政策说明
  • 防御措施:删除无用,锁定目录才有效
    • macOS 系统操作方法
    • Linux 系统操作方法
    • 操作影响及恢复方法
  • 总结思考

故事始于一次释放磁盘空间时的常规检查:`~/.zcode` 文件夹占用了超过 700MB 的空间。经过断断续续的深入探究,发现了一件相当惊人的事:只要登录了 ZCode(智谱官方推出的 AI 编码桌面应用),它就会悄无声息地将整个工作区——包括完整的 `.git` 历史记录、LFS 资产缓存、引用日志以及全局应用配置等——进行打包、加密,然后直接上传到阿里云 OSS。更具讽刺意味的是,用于加密的 RSA 公钥由服务器动态提供,而私钥则仅存在于云端。无法解密保存在自己磁盘上的数百兆字节的密文,ZCode 客户端本身也做不到。以下是完整的调查记录、证据链,以及一个能永久阻止该行为的简单防御方法。

起始点:一个 313MB 的存档文件处于待处理状态

`~/.zcode` 是 ZCode 的数据根目录。其大小分布大致如下:

  • `cli/`:约 257MB(会话数据库、执行日志)
  • `computer - use/`:约 130MB(捆绑的应用程序和运行时依赖项)
  • `v2/checkpoints/`:约 303MB(主要嫌疑对象)

在 `v2/checkpoints/` 目录中,发现了一个 313MB 的 `.enc` 文件和一个状态元数据文件:

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

事情的经过很简单:

  1. 客户端扫描了正在进行的商业项目,排除了 `node_modules` 等文件夹后,将剩余的 345MB 内容打包成一个 313MB 的加密存档,标记为 `baseline`(完整快照)。
  2. 客户端记录了 564 次上传失败的尝试,该文件便一直留在本地的 `pending/` 目录中,等待下一次重试。

该仓库总大小为 10GB,去除依赖项后,剩余的 345MB 几乎全是核心知识产权内容。

去向追踪:从日志到 asar 文件逆向工程

日志中没有明确的上传 URL,于是对客户端的 `app.asar` 文件进行了解析。重构后的上传流程如下:

sequenceDiagram    participant C as ZCode 客户端    participant S as zcode.z.ai    participant O as 阿里云 OSS    C->>S: POST /api/v1/snapshot/upload - credential    S-->>C: snapshot_id + RSA 公钥 + 最大大小 + OSS 表单凭证 + 回调信息    C->>C: tar.gz 打包 → AES - 256 - CTR 加密 → RSA - OAEP 密钥包装    C->>O: 直接上传 tar.gz.enc 文件    O->>S: 回调确认接收

整个上传流程分为两个阶段:

  1. 向协调器请求凭证:客户端调用 `https://zcode.z.ai`(代码中的 `VITE_ZCODE_ENDPOINT_ORIGIN`)。服务器返回 OSS 表单签名(`policy`、`x - oss - signature`)、动态对象键、大小限制以及本次加密使用的 RSA 公钥。
  2. 直接通过表单 POST 到 OSS:客户端在本地完成存档和流式加密后,绕过 ZCode 自身的应用服务器,通过 HTTP POST 表单直接将 `tar.gz.enc` 文件上传到阿里云 OSS。OSS 随后会回调智谱的后端服务器,注册该快照。

通过检查活动套接字,证实了这一点:运行中的 ZCode 进程与 `zcode.z.ai` 的 IP 端点以及两个阿里云 OSS 存储节点保持着持久的 HTTPS 连接。

最具讽刺意味的部分:加密密钥归服务器所有

加密实现采用了标准的信封加密方式:

{    "keyId": String(i.encryption.key_version),    "keyWrapAlgorithm": "rsa - oaep - sha256",    "publicKeySpkiPem": Ylt(i.encryption.public_key)}
  • 内容使用临时对称密钥通过 AES - 256 - CTR 算法进行加密。
  • 对称密钥使用服务器提供的公钥通过 RSA - OAEP - SHA256 算法进行包装。

关键问题在于这个公钥:它是在凭证协商过程中由服务器提供的,而对应的私钥从未接触过设备。正如预期的那样,使用系统上的所有本地私钥尝试解开信封密钥均以失败告终。换句话说,磁盘上的 313MB 密文,无论是自己还是客户端都无法打开。只有智谱的后端服务器拥有解锁它的密钥。如果这个功能真的是为了方便用户进行回滚操作或跨设备同步,那么密钥应该保存在本地(就像 Git 或 Time Machine 那样)。只有服务器能使用的密钥,其唯一目的就是确保服务器可以随时读取代码。

打包内容分析:近 90% 是 .git 目录

尽管密文被锁定,但打包过程中生成的清单(文件列表)以明文形式保存在本地。对包含 42,411 个文件的快照进行分析后发现:

内容大小占比包含信息
.git/lfs/196.1 MB56.8%LFS 缓存——所有曾经下载过的二进制资产和大型媒体文件
.git/objects/102.2 MB29.6%完整的提交历史对象存储(提交记录、树对象、数据块)
.git/logs/0.6 MB0.2%引用日志——本地分支历史和未推送的操作记录
源代码和文档约 46.2 MB13.4%`src/` 目录、配置文件、内部文档

仅 `.git` 目录就占了整个有效负载的 86.6%。一旦上传,云端接收到的远不止当前的工作目录,而是自仓库创建以来的整个历史记录:

  • 后续提交中已删除的历史 API 密钥和敏感配置信息。
  • 未推送的本地分支名称(这可能会泄露未发布的功能计划)。
  • `.git/config` 文件中配置的内部 GitLab 主机名和仓库路径。

此外,还有一个名为 `repo_snapshot_extra_manifest` 的额外清单,它会对全局 ZCode 配置文件(如 `settings.behavior.json`)进行哈希处理,并将其与每个快照一起跨工作区打包。

开关真相:界面设置无法阻止上传

人们的第一反应通常是查看设置选项,尝试关闭该功能。将界面选项与代码库进行了对比:

开关你期望的功能实际功能
**优化体验** (`optimizeAgentExperienceEnabled`)禁用遥测功能/数据收集仅控制数据是否被授权用于模型训练。快照捕获和上传操作仍会继续
**仓库快照索引** (`repoSnapshotIndexingEnabled`)禁用快照功能仅控制服务器是否对上传的快照进行索引。本地的打包和上传操作不受影响

查看主机汇编代码后可以清楚地看到:捕获/上传的辅助进程在启动时会无条件实例化。代码中没有根据用户偏好设置的条件判断,唯一的要求是 `tokenProvider` 能够返回有效的 JWT 令牌。总结来说,只要登录了,这个后台上传流程就会一直处于活跃状态,任何界面设置都无法将其关闭。捕获操作会在两个时间点触发:`captureBeforePrompt`(每次提示之前)和标记为 `repo - wiki - update` 的任务完成时。在会话日志中,一个活跃会话最多可产生 62 次捕获事件。

隐私政策说明

查看 ZCode 的隐私政策,其中明确提到会收集“对话过程中提交的文本、文件和代码”——这是为大语言模型提供上下文的常见做法。然而,在整个隐私政策、常见问题解答和更新日志中,没有一处提到会悄无声息地打包并上传整个工作区和完整的 Git 历史记录。最接近相关内容的表述是一个通用模板声明:“优化程序默认关闭,未经同意,输入数据不会用于训练”。

防御措施:删除无用,锁定目录才有效

当最初发现待处理的打包文件时,直接将其删除了。但不到半小时,它又重新捕获并生成了一个新的 313MB 存档,重试计数器从 564 增加到了 565。上传程序发现文件丢失后,会立即重新打包。手动删除根本无法解决问题。最干净、有效的解决方案是在文件系统层面设置不可变标志,从内核层面拒绝写入操作:

macOS 系统操作方法
# 清空并锁定检查点目录rm - rf ~/.zcode/v2/checkpointsmkdir - p ~/.zcode/v2/checkpointschflags uchg ~/.zcode/v2/checkpoints# 验证:应输出 "Operation not permitted"touch ~/.zcode/v2/checkpoints/test
Linux 系统操作方法
# 清空并锁定检查点目录rm - rf ~/.zcode/v2/checkpointsmkdir - p ~/.zcode/v2/checkpointsudo chattr + i ~/.zcode/v2/checkpoints# 验证:应输出 "Operation not permitted"touch ~/.zcode/v2/checkpoints/test
操作影响及恢复方法
  • 结果:每当捕获逻辑尝试进行磁盘 I/O 操作时,都会被内核阻止。由于没有本地文件,上传流程也就无内容可传。
  • 权衡:“检查点回滚/时间线”界面功能将无法使用(该功能本身就需要上传代码)。但正常的聊天、自动完成和工具执行不受影响。日志中出现的 I/O 错误可以忽略。
  • 恢复方法:在 macOS 系统中运行 `chflags nouchg ~/.zcode/v2/checkpoints`,在 Linux 系统中运行 `sudo chattr - i ~/.zcode/v2/checkpoints`。

总结思考

使用 AI 工具时,模型推理不可避免地需要代码上下文,这是大家都能接受的。但 ZCode 的这种行为在两个方面明显越界了:首先,数据范围。推理过程只会发送与任务相关的上下文,而快照上传会泄露整个仓库以及多年的 Git 提交历史。其次,架构设计。如果这个功能真的是为了方便用户进行恢复或同步操作,解密密钥应该归用户所有。加密密钥仅由服务器持有,隐私政策中未披露相关信息,后台上传无法停止,删除文件后还会重新打包——这看起来更像是数据收集,而非备份功能。工具只是工具,用户必须明确自己的底线。如果软件不让关闭某个功能,那就利用操作系统内核将其限制住。

代码下载链接: https://pan.quark.cn/s/37189d21223e STM8S103F3属于STMicroelectronics公司研发的STM8S系列微控制器,该芯片在众多嵌入式系统设计中得到普遍应用,尤其是在对低能耗与高性能有较高要求的场景中。这款微控制器内置8位中央处理器,配备了完整的数字信号处理工具集,涵盖了定时器单元、串行通信端口以及多种外部设备接口。 无线供电方案是基于STM8S103F3构建的,其核心目标在于达成无需物理接触的电能传输。这项技术主要运用电磁感应理论,借助发送端与接收端线圈间磁场的变化来实现能量传递。在无线供电架构中,STM8S103F3通常担任控制核心的角色,负责监督并调节充电环节中的各项指标,以此确保操作安全并提升工作效率。 1. **ADC(模拟数字转换器)**:在无线供电系统中,ADC负责将探测到的电压或电流信号转换为数字形式,使微控制器能够进行解析与操控。例如,它可用于测量接收端线圈的电压值,借此评估充电状况及效能。 2. **PWM(脉宽调制)**:PWM是调控电源输出的常用手段,通过变更脉冲宽度来控制平均功率输出。在无线供电系统中,PWM或许会用于调节发射端功率的输出水平,以应对不同的充电需求及距离差异。借助精准控制PWM信号,能够维持充电电流的稳定,进而保障设备安全进行充电。 3. **软件体系**:无线供电方案可能由多个组成部分构成,例如初始设定、异常识别、通信规约处理等。这些组件通过周密规划的架构协同运作,共同完成无线供电的全部功能。 4. **安全功能**:方案可能集成过温、过压、过流防护机制,一旦侦测到非正常情形,可自动中断电源供应或降低功率输出,以避免设备受损。 5. **通信规约**:无...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值