Claude Code 源码泄露事件始末:从泄露原因到工程借鉴
Claude Code 源码泄露事件始末:从泄露原因到工程借鉴
TL;DR 2026年3月,Claude Code 因 npm 包中遗留 source map 文件导致源码泄露,约 1906 个文件、512000+ 行 TypeScript 代码暴露。这是 Anthropic 第二次犯同样的错误。泄露代码揭示了 Claude Code 的技术栈(Bun + TypeScript + React/Ink)、40+工具系统、50+命令,以及多个安全 Bug。本文整理事件始末、技术细节、安全问题和工程借鉴。
作者:yuumingwen
事件概述
2026年3月,GitHub 上出现了一个名为 claude-code-source 的代码仓库,据称是 Claude Code 的源码遭到泄露。仓库迅速获得大量关注,截至报道时已超过 5400 Star 和 8800 Fork。Hacker News 上讨论热烈,DEV Community、各区块链媒体也在纷纷转载。
泄露原因
Anthropic 在发布 Claude Code 的 npm 包时,将 source map 文件一起打包发布了。Source map 是 JavaScript 开发中的调试文件,作用是将压缩混淆后的代码映射回原始源码。本来应该通过以下方式排除:
.npmignore文件中排除package.json的files字段中过滤
结果两件事都没做。一个 60MB 的 cli.js.map 文件,就这么明晃晃地躺在 npm 包里。任何人下载这个包,就能还原出完整的 TypeScript 源码——1906 个文件,512000 多行代码,全部暴露。
历史重演
这不是第一次了。 2025年2月 Claude Code 刚发布时,就因为同样的原因泄露过一次。当时 Anthropic 删除了旧版 npm 包并去掉了 source map。结果 2026年3月又以同样的方式再次泄露。
源码技术分析
技术栈
| 组件 | 技术选型 |
|---|---|
| 语言 | TypeScript |
| 运行时 | Bun |
| 终端 UI | React + Ink(用 React 组件来画终端界面) |
| CLI 解析 | Commander.js |
| Schema 校验 | Zod v4 |
工具系统
Claude Code 的工具系统设计得相当工程化:
- 40+ 个独立工具模块:每一个都有自己的输入 Schema、权限模型和执行逻辑
- BashTool:负责执行 Shell 命令
- FileReadTool:读取文件
- GrepTool:做内容搜索(底层使用 ripgrep)
- AgentTool:负责派生子 Agent
命令系统
- 50+ 个斜杠命令:覆盖开发工作流的方方面面,包括
/commit、/review、/vim、/doctor等
Feature Flag 机制
代码中大量使用 Feature Flag,通过 Bun 的编译时常量折叠实现:
const voiceCommand = feature('VOICE_MODE')
? require('./commands/voice/index.js').default
: null
部分 Flag 名称及疑似功能:
| Flag 名称 | 疑似功能 |
|---|---|
| KAIROS | 助手模式 |
| PROACTIVE | 主动模式 |
| TORCH | - |
| TUNGSTEN | - |
| FENNEC | - |
彩蛋功能 BUDDY:一个电子宠物风格的 ASCII 伴侣精灵,原本计划作为愚人节彩蛋上线,结果彩蛋还没发出去,源码先漏了。
内部用户区分
代码中使用 process.env.USER_TYPE === 'ant' 来区分 Anthropic 内部员工和外部用户。内部员工可以使用 ConfigTool、TungstenTool、REPLTool 等额外工具和命令。
安全问题发现
安全审查对权限系统、文件写入、远程连接等高风险路径进行了分析,发现了以下几个 Bug:
1. Plan 文件白名单匹配过宽
代码使用 startsWith 做前缀匹配来判断某个文件是否属于当前 session 的 Plan 文件。但匹配范围过大——如果当前 planSlug 是 blue-fox,则 blue-fox-backup.md、blue-fox-evil.md 等文件都会被当作合法 Plan 文件,绕过权限检查。
2. 多级 Symlink 处理不完整
代码想实现"写穿 symlink 同时保留链接本身"的效果,但只调用了一次 readlinkSync。多级链接链(如 link1 -> link2 -> target)会导致中间的 symlink 被普通文件替换,链接结构被静默破坏。
3. WebSocket 重连回放跨运行时不一致
WebSocket 重连回放在 Node 和 Bun 两个运行时下行为不一致,可能导致断线重连后消息丢失。
安全设计评价
这些 Bug 并不是代码写得乱导致的。恰恰相反,这套权限系统明显经过了高强度的安全补丁演进,对 UNC 路径、Shell 展开、symlink 逃逸、glob 绕过都有防御。问题出在系统复杂度本身——白名单写宽了、多层防御的某一层没覆盖到边界情况。
工程借鉴
启动性能优化
main.tsx 的前 20 行,在任何 import 语句之前,就用副作用触发了 MDM 配置读取和 macOS 钥匙串预取。利用后续模块加载的约 135 毫秒窗口做并行预热,实测能节省 65 毫秒的启动时间。
模块懒加载
重型模块全部使用动态 import 延迟加载,只在真正需要时才拉进来:
- OpenTelemetry:约 400KB
- gRPC:约 700KB
做 CLI 工具时,在每一毫秒上锱铢必较的优化思路值得参考。
影响评估
对普通用户
无直接影响。泄露的是 CLI 客户端代码,不涉及模型权重,也不涉及用户数据。
对 Anthropic
同一个问题犯两次就不太好解释了:
- npm 打包配置问题:CI/CD 流水线里加一个 check 就能防住,结果愣是没防住
- 同期其他泄露:据 Fortune 报道,差不多同一时间,Anthropic 还把未发布模型的信息和内部 CEO 活动细节暴露在了公开数据库里
经验教训
发 npm 包之前,永远检查一下你的
.npmignore和package.json的files字段。source map、.env、内部配置,漏出去一个就是大事故。
防范措施
- 在
.npmignore中排除调试文件和敏感配置 - 在
package.json的files字段中明确列出需要打包的文件 - CI/CD 流水线中加入 source map 检查步骤
- 发布前使用
npm pack --dry-run检查实际打包内容
相关链接
- GitHub 仓库:https://github.com/instructkr/claude-code
- 微信公众号文章:https://mp.weixin.qq.com/s/ssxPswUL-eVdhkcBuwPP_w

浙公网安备 33010602011771号