2026 年 3 月 31 日,Anthropic 的 AI 编码工具 Claude Code 因 npm 打包配置失误,完整暴露了约 51.2 万行 TypeScript 源代码。本文从技术层面深度复盘这次事故,并解析泄露代码中揭示的 Agent 架构设计。

一、事故经过:一份不该出现的 .map 文件

1.1 什么是 Source Map?

Source Map(源代码映射)是前端开发中的常见调试工具。它的作用是将打包压缩后的代码映射回原始源代码,方便开发者在浏览器 DevTools 中调试。

一个典型的 source map 文件长这样:

{
  "version": 3,
  "sources": ["../src/index.ts", "../src/agent/loop.ts"],
  "sourcesContent": ["// 这里是完整的原始源代码..."],
  "mappings": "AAAA,IAAI..."
}

关键字段是 sourcesContent —— 它直接包含了原始代码的全文。这也是为什么 source map 绝对不能被发布到生产环境

1.2 泄露过程

事件的时间线很清晰:

  1. Anthropic 发布 Claude Code v2.1.88 到 npm registry (@anthropic-ai/claude-code)
  2. 该版本的产物中意外包含了一个 59.8 MB 的 .map 文件
  3. 安全研究员 Chaofan Shou 在例行扫描中发现异常文件大小
  4. 通过标准的 source map 解析,还原出约 1,900 个 TypeScript 源文件,共 51.2 万行代码
  5. 代码迅速被镜像备份并在社区传播

Anthropic 随后确认这是「人为错误导致的发布打包问题」,不涉及任何用户数据或凭证。

1.3 为什么这种事会发生?

这个问题其实很有代表性。在现代 JavaScript/TypeScript 项目中,构建流程大致如下:

TypeScript 源码
    ↓ (tsc / esbuild / webpack)
压缩混淆的 JS bundle
    ↓ (可选)
Source Map 文件 (.map)
    ↓ (npm publish)
npm registry

正常情况下,.map 文件应该被 .npmignorepackage.jsonfiles 字段排除在发布产物之外。但如果构建配置有疏忽 —— 比如忘了在 .npmignore 中添加 *.map,或者 files 字段写得太宽泛 —— 这些调试产物就会被一并发布。

# 一个简单的检查方法:在发布前用 npm pack --dry-run 查看将被发布的文件
npm pack --dry-run

# 或者直接解压检查已发布的包
npm pack @anthropic-ai/claude-code@2.1.88
tar -xzf anthropic-ai-claude-code-2.1.88.tgz
ls -alh package/  # 看到 59.8MB 的 .map 文件就该警觉了

教训:这类事故往往不是某个人的失误,而是 CI/CD pipeline 中缺少了一道「发布前检查」的关卡。


二、泄露代码揭示的 Agent 架构

这次泄露最有价值的部分,是它完整展示了一个生产级 AI Agent 的真实架构。这不是论文里的原型系统,而是日活百万级的产品代码。

2.1 核心引擎:单线程主循环

Claude Code 的核心是一个代号为 nO 的单线程主循环引擎:

┌─────────────────────────────────────┐
│           Master Loop (nO)           │
│                                     │
│   User Input                        │
│       ↓                             │
│   LLM Call (with tools)             │
│       ↓                             │
│   Tool Result → Loop continues?     │
│       ↓     YES → back to LLM Call  │
│       ↓     NO  → Return to User    │
│                                     │
└─────────────────────────────────────┘

设计哲学很直白:只要模型返回了 tool_call,就继续执行。没有复杂的状态机,没有多线程竞争。一个简洁的 while 循环搞定一切。

这种设计的好处在于:

  • 可调试:单线程下复现 bug 非常容易
  • 可控:任何时刻都能准确知道 Agent 在做什么
  • 可中断:用户随时可以 Ctrl+C 终止

2.2 工具系统:40+ 内置工具的模块化设计

泄露代码显示 Claude Code 内置了约 40 多个工具,采用插件式架构:

// 工具定义的大致结构(示意)
interface Tool {
  name: string;
  description: string;
  parameters: JSONSchema;
  execute(params: Record<string, any>): Promise<ToolResult>;
  // 权限控制
  requiresPermission: PermissionLevel;
}

工具大致分类:

类别 工具示例 说明
文件操作 read_file, write_file, list_dir 本地文件读写
终端命令 bash, exec 执行 Shell 命令
搜索 grep, glob, semantic_search 代码搜索
浏览器 browse_web, screenshot 网页交互
子任务 spawn_agent, delegate_task 多Agent 编排
记忆 read_memory, update_memory 项目记忆管理

工具的权限控制分层设计值得关注 —— 不同级别的操作需要不同级别的用户确认,这是 AI 安全的重要实践。

2.3 记忆系统:自愈式分层架构

传统 Agent 的记忆方案通常是「把所有上下文塞进 prompt」,这在长项目中很快会撑爆 context window。

Claude Code 的方案是分层索引 + 按需加载

┌─────────────────────────────┐
│      MEMORY.md (轻量索引)     │
│  - 项目概览                   │
│  - 关键文件位置指针            │
│  - 最近修改摘要               │
└───────────┬─────────────────┘
            │ 按需加载
            ↓
┌─────────────────────────────┐
│     Project Knowledge       │
│  - 详细代码结构               │
│  - 依赖关系图                │
│  - 历史决策上下文             │
└─────────────────────────────┘

MEMORY.md 只存储指针和摘要,体积很小(通常 < 200 行),始终在 context 中。当需要深入了解某个模块时,才通过工具去加载对应的详细信息。

更有意思的是自愈机制:当 MEMORY.md 中的信息与实际代码产生矛盾时,系统会自动触发校正,更新索引。这解决了记忆腐化(memory staleness)的老问题。

2.4 多 Agent 编排

泄露代码中包含了完整的子 Agent 生成和调度逻辑:

Main Agent (用户交互)
    │
    ├── spawn Worker Agent 1 (处理文件 A)
    ├── spawn Worker Agent 2 (处理文件 B)
    └── spawn Worker Agent 3 (跑测试)
         │
         ↓ 聚合结果
    Main Agent (继续推理)

关键设计点:

  • 隔离的 Context Window:每个子 Agent 有独立的上下文,避免主 Agent 上下文被撑爆
  • 受控并行:并行数量有上限,避免 API 调用风暴
  • 结果聚合:子 Agent 的输出经过压缩后再返回主 Agent

这种设计本质上是把「一个超级 Agent」拆成了「一个调度者 + 多个专家」,非常类似微服务架构的思路。


三、未公开功能:KAIROS 与 Undercover Mode

泄露代码中发现了两个尚未正式发布的功能,它们的设计思路很值得分析。

3.1 KAIROS:永远在线的自主守护进程

KAIROS(取自古希腊语「恰当的时机」)是一个自主后台 Agent 模式。核心概念:当用户不工作时,Agent 仍在后台持续思考和优化

它的关键子系统叫 autoDream(自动做梦):

用户 Idle(离线/休眠)
    ↓
KAIROS Daemon 启动
    ↓
autoDream 进程:
  1. 回顾当日所有对话和操作
  2. 合并碎片化的观察
  3. 解决逻辑矛盾
  4. 将模糊洞察转化为确定性事实
  5. 更新 MEMORY.md
    ↓
用户回来时 → Agent 拥有更清晰的项目理解

代码中还发现了以下基础设施:

  • Cron 调度(每 5 分钟触发一次思考循环)
  • GitHub Webhook 订阅(实时感知代码变更)
  • 后台 Worker 进程管理

技术意义:这可能是第一个将 Agent 设计为 daemon 进程(而非 request-response 模式)的生产级实现。它模糊了「工具」和「队友」的边界。

3.2 Undercover Mode:卧底模式

这个功能听起来很戏剧化,但背后的工程问题很真实:

场景:Anthropic 的员工用 Claude Code 给开源项目提交代码。如果 AI 在 commit message 里写了 “Generated by Claude Code” 或者引用了内部代号,就会暴露 Anthropic 的参与。

Undercover Mode 的解决方案是通过 System Prompt 注入严格的保密指令:

你正在 UNDERCOVER 模式下运行...
你的 commit message 绝不能包含任何 Anthropic 内部信息。
不要暴露你的身份。

禁止提及:
- "Claude Code" 或 "Anthropic"
- 内部代号("Tengu"、"Capybara"、"Fennec"、"Numbat")
- 内部 Slack 频道或项目名称
- 添加 "Co-Authored-By" 归属行

工程实现上的几个细节:

  1. 单向门设计:环境变量可以强制开启 Undercover Mode,但不能强制关闭
  2. 编译时消除:在对外发布的版本中,这部分代码通过 dead-code elimination 被移除
  3. 多层检查:不仅检查 commit message,还检查代码注释和变量命名

3.3 反蒸馏机制

代码中还发现了 ANTI_DISTILLATION_CC 标志,用于防止竞争对手通过 Claude Code 的输出来训练自己的模型:

原理:当检测到可能的蒸馏行为时,系统会在 API 响应中注入假工具定义,污染潜在的训练数据。

这是一个有趣的对抗设计 —— 用「数据投毒」对抗「知识蒸馏」。


四、泄露中的内部代号与模型路线图

泄露代码还意外暴露了 Anthropic 的内部模型代号:

内部代号 对应模型 说明
Capybara Claude 4.6 变体 当前主力模型
Fennec Opus 4.6 高端推理模型
Tengu 未知 出现在路线图中
Numbat 测试中的新模型 可能是下一代

这些代号原本应该通过 Undercover Mode 被严格保密 —— 结果因为 source map 泄露而公之于众,颇具讽刺意味。


五、供应链安全:npm 生态的老问题

这次事件发生的时间点很巧 —— 大约同一时间,Claude Code 依赖的 axios 包也出现了供应链安全事件。两件事叠加,引发了社区对 npm 生态供应链安全的广泛讨论。

5.1 你的 npm 发布流程是否安全?

一个健壮的发布前检查清单:

# 1. 检查将要发布的文件列表
npm pack --dry-run 2>&1 | head -50

# 2. 检查包大小是否异常
npm pack --dry-run 2>&1 | tail -1
# 如果包体积突然增大几十 MB,一定有问题

# 3. 在 .npmignore 中明确排除敏感文件
cat .npmignore
# 应包含:
# *.map
# .env*
# src/         (如果只发布编译产物)
# __tests__/
# .github/

# 4. 或者用 package.json 的 files 字段做白名单(更安全)
# {
#   "files": ["dist/", "README.md", "LICENSE"]
# }

5.2 CI/CD 中的自动化防线

在发布 pipeline 中加入以下检查:

# GitHub Actions 示例
- name: Check package size
  run: |
    SIZE=$(npm pack --dry-run 2>&1 | tail -1 | grep -o '[0-9.]*' | head -1)
    MAX_SIZE=5  # MB
    if (( $(echo "$SIZE > $MAX_SIZE" | bc -l) )); then
      echo "Package size ($SIZE MB) exceeds limit!"
      exit 1
    fi

- name: Check for source maps
  run: |
    npm pack
    TARBALL=$(ls *.tgz)
    if tar -tzf "$TARBALL" | grep -q '\.map$'; then
      echo "Source map files detected in package!"
      exit 1
    fi

5.3 依赖审计

# 定期审计依赖
npm audit

# 检查依赖的 source map 或敏感文件
npx depcheck

# 使用 lockfile 锁定依赖版本,防止供应链注入
npm ci  # 而不是 npm install

六、总结与反思

技术层面

  1. Source Map 是一把双刃剑:方便了调试,但把它带进生产发布就是裸奔
  2. Claude Code 的 Agent 架构设计成熟度很高:单线程主循环 + 模块化工具 + 分层记忆 + 多 Agent 编排,是当前 AI Agent 工程化的标杆
  3. KAIROS(Always-On Agent)代表了 Agent 发展的一个方向:从被动响应到主动思考,从工具到伙伴
  4. 反蒸馏机制(Anti-Distillation):在 AI 产品竞争中,保护输出的知识产权正在成为新的工程挑战

工程实践层面

  1. 发布流程需要「关卡」:不能靠人记住「发布前删掉 .map 文件」,要靠 CI/CD 自动化检查
  2. npm 包大小是一个有效的预警信号:59.8 MB 的 source map 混在发布产物中,一个简单的文件大小阈值检查就能拦住
  3. 供应链安全不是 optional 的事:尤其是 AI 工具这类高权限软件,每一个依赖都是攻击面

最后说一句:虽然代码被泄露了,但 Claude Code 依然是闭源专有软件。泄露代码不等于开源。擅自复制、分发或使用其源代码可能面临法律风险。本文仅基于公开报道进行技术分析,不涉及对泄露代码本身的引用。

如果你也在用 AI API 做产品,建议考虑统一 API 网关方案。
我自己在用的是 Praka.ai —— 支持 GPT、Claude、Gemini、DeepSeek 等 100 多个模型,接入方式兼容 OpenAI SDK,改一行 base_url 就能用。


有任何问题或者想讨论的,欢迎评论区交流 👇

觉得有用的话,点个赞收藏下次找得到 🙏

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐