
2026 年 3 月 31 日,安全研究员 Chaofan Shou 在 X 上发了一条帖子:
"Claude Code source code has been leaked via a map file in their npm registry!"
这条帖子迅速引爆 AI 社区,获得超过 2800 万次浏览。
事情的经过是这样的:2026 年 3 月 30 日,Anthropic 发布 Claude Code v2.1.88,包体经过混淆,但不小心把一个 57MB 的 source map 文件(cli.js.map)一起打包进了 npm 包。这个文件里嵌入了完整的、未混淆的 TypeScript 源代码——约 2000 个文件,超过 51.2 万行代码。任何人只需 npm pack 或直接浏览 npm registry,无需任何漏洞利用或特殊权限,就能拿到全部源码。
Chaofan Shou 于 3 月 31 日 UTC 08:23 公开披露,Anthropic 当天即下架该版本,但为时已晚。GitHub 上的镜像仓库迅速涌现,其中一个积累了超过 8.4 万 star 和 8.2 万 fork。
Anthropic 官方随后确认:
"这是一次由人为失误导致的发布打包问题,不是安全漏洞。没有客户数据或凭证被暴露。"
值得注意的是,这已经是 Claude Code 在一年内第二次通过 source map 泄漏源码。
Anthropic 官方声明:
"没有敏感客户数据或凭证被暴露。这是一次由人为失误导致的发布打包问题,不是安全漏洞。"
注:本文基于这份代码分析 Claude Code 的内部架构,仅供学习研究。正如开发者 Justin Schroeder 所说:"源码可见不等于开源,复制或重新分发仍然违反许可协议。"
先看 package.json,技术选型很有意思:
运行时:Bun,不是 Node.js
"scripts": {
"build": "bun build src/entrypoints/cli.tsx --outdir dist --target bun",
"dev": "bun run src/entrypoints/cli.tsx"
}Anthropic 选择了 Bun 作为运行时,主要原因是启动速度。Claude Code 是一个交互式 CLI 工具,冷启动延迟直接影响用户体验。Bun 的启动速度比 Node.js 快 3-4 倍。
UI 框架:React + Ink
终端 UI 用的是 Ink[1],一个把 React 渲染到终端的框架。这意味着整个 REPL 界面是用 React 组件写的,有完整的状态管理、hooks、甚至还用了 React Compiler 做性能优化。
构建产物:单文件 bundle
bun build src/entrypoints/cli.tsx --outdir dist --target bun
# 输出 dist/cli.js,约 25MB整个应用打包成一个 25MB 的单文件,这就是为什么 npm install -g @anthropic-ai/claude-code 之后可以直接用 claude 命令。
src/entrypoints/cli.tsx 是真正的入口文件,里面有一个很有意思的设计——分级快速路径:
async functionmain(): Promise<void> {
const args = process.argv.slice(2);
// 快速路径:--version 零模块加载
if (args.length === 1 && (args[0] === "--version" || args[0] === "-v")) {
console.log(`${MACRO.VERSION} (Claude Code)`);
return;
}
// 加载启动性能分析器
const { profileCheckpoint } = awaitimport("../utils/startupProfiler.js");
profileCheckpoint("cli_entry");
// ... 其他快速路径
// 最后才加载完整 CLI
const { main: cliMain } = awaitimport("../main.jsx");
awaitcliMain();
}--version 命令完全不加载任何模块,直接输出版本号返回。其他命令也有各自的快速路径,只有真正需要交互的场景才加载完整的 CLI 模块。
文件顶部还有一个关键的 polyfill:
const feature = (_name: string) => false;这是 Anthropic 内部 feature flag 系统的 polyfill。原始代码里大量使用 feature('FLAG_NAME') 来控制功能开关,包括 COORDINATOR_MODE、KAIROS、PROACTIVE 等内部实验性功能,在还原版本里全部返回 false。
src/query.ts 是整个系统的心脏,实现了一个复杂的异步生成器循环:
export async function* query(
params: QueryParams,
): AsyncGenerator<StreamEvent | RequestStartEvent | Message | ...> {
const terminal = yield* queryLoop(params, consumedCommandUuids)
return terminal
}这个循环处理了很多复杂场景:
1. 自动压缩(Auto Compact)
当对话历史太长接近 context window 上限时,自动触发压缩:
const { compactionResult } = await deps.autocompact(
messagesForQuery,
toolUseContext,
{ systemPrompt, userContext, ... },
querySource,
tracking,
snipTokensFreed,
)
if (compactionResult) {
// 用摘要替换历史消息,继续对话
const postCompactMessages = buildPostCompactMessages(compactionResult)
messagesForQuery = postCompactMessages
}2. 工具调用循环
模型返回 tool_use 时,执行工具并把结果喂回去,形成一个多轮循环:
while (true) {
// 调用模型
forawait (const message of deps.callModel({ messages, ... })) {
if (message has tool_use) {
needsFollowUp = true
}
}
// 执行工具
if (needsFollowUp) {
const toolResults = awaitrunTools(toolUseBlocks, ...)
state.messages = [...messages, ...toolResults]
continue
}
break// 没有工具调用,结束
}3. 流式降级(Streaming Fallback)
当流式响应失败时,自动降级到非流式请求:
if (streamingFallbackOccured) {
// 清理孤立的消息,避免 API 报错
for (const msg of assistantMessages) {
yield { type: 'tombstone', message: msg }
}
// 重新开始,用非流式模式
}src/services/api/claude.ts 是 API 客户端,支持四个提供商:
通过 ANTHROPIC_BASE_URL 环境变量可以把请求转发到任何兼容 Anthropic API 格式的服务,这也是为什么可以用 MiniMax、DeepSeek 等国内模型来驱动 Claude Code。
Prompt Caching 优化
代码里有精细的 prompt cache 控制:
export function getCacheControl({ scope, querySource } = {}) {
return {
type: 'ephemeral',
...(should1hCacheTTL(querySource) && { ttl: '1h' }),
...(scope === 'global' && { scope }),
}
}对于付费订阅用户,系统会自动启用 1 小时 TTL 的 prompt cache,大幅降低重复内容的 token 消耗。
彩蛋:负面情绪过滤器
泄漏的代码里,Hacker News 用户发现了一个有趣的细节:代码中存在一个包含大量脏话的正则表达式,用于检测用户提示词中的负面情绪。这说明 Anthropic 在工程层面对用户体验做了相当细致的处理。
这次泄漏最引人关注的部分,是几个从未对外宣布过的功能:
KAIROS — 持久后台 Agent 模式
一个可以在后台自主运行任务的 Agent,能在不等待用户输入的情况下自动修复错误,并通过推送通知告知用户结果。
Dream Mode — 持续后台推理
设计用于在后台持续推理,独立开发和迭代想法。
Undercover Mode — 最受关注的发现
系统提示里有这样一段指令:
"You are operating UNDERCOVER in a PUBLIC/OPEN-SOURCE repository. Your commit messages, PR titles, and PR bodies MUST NOT contain ANY Anthropic-internal information. Do not blow your cover." (你正在一个公开/开源仓库中卧底运行。你的 commit 信息、PR 标题和 PR 描述中绝对不能包含任何 Anthropic 内部信息。不要暴露你的身份。)
Anti-distillation 投毒
代码中存在向 API 响应注入虚假工具定义的机制,用于干扰竞争对手抓取 Claude Code 输出来训练自己模型的行为。
src/tools/ 目录下有 40+ 个工具,每个工具独立一个目录,结构统一:
src/tools/BashTool/
├── BashTool.tsx # 工具实现
├── prompt.ts # 工具描述(给模型看的)
├── UI.tsx # 终端 UI 组件
├── bashSecurity.ts # 安全检查
└── bashPermissions.ts # 权限控制工具接口定义在 src/Tool.ts:
type Tool = {
name: string
description: string
inputSchema: JSONSchema
call(input, context): AsyncGenerator<ToolResult>
// 可选:终端 UI 渲染组件
renderResult?: React.Component
}权限系统
每个工具调用都经过权限检查,有五种模式:
default:每次询问用户acceptEdits:自动接受文件编辑dontAsk:自动接受所有操作bypassPermissions:完全跳过权限检查(危险模式)plan:只规划不执行~/.claude/settings.json这是很多人不知道的细节。Claude Code 启动时会自动读取 ~/.claude/settings.json,并把 env 字段注入到 process.env:
export const getClaudeConfigHomeDir = memoize(
(): string => {
return (
process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), '.claude')
).normalize('NFC')
},
)所以只需要在 settings.json 里配置:
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic",
"ANTHROPIC_AUTH_TOKEN": "your-token",
"ANTHROPIC_MODEL": "MiniMax-M2.7"
}
}就能让 Claude Code 使用任何兼容 Anthropic 格式的模型,完全不需要修改代码。
这份还原的代码是可以直接运行的:
# 安装依赖
bun install
# 测试
echo "你好" | bun run src/entrypoints/cli.tsx -p
# 输出:你好!有什么我可以帮助你的吗?
# 查看版本
bun run src/entrypoints/cli.tsx --version
# 输出:2.1.888 (Claude Code)
# 交互模式
bun run devcli.tsx (入口)
└── main.tsx (Commander.js CLI)
├── screens/REPL.tsx (交互界面,React/Ink)
│ └── QueryEngine.ts (会话管理)
│ └── query.ts (核心循环)
│ ├── services/api/claude.ts (API 调用)
│ ├── services/compact/ (上下文压缩)
│ └── services/tools/ (工具执行)
└── tools/ (40+ 工具)
├── BashTool
├── FileEditTool
├── GrepTool
└── AgentTool (子 Agent)几个值得学习的设计点:
AsyncGenerator 传递数据,背压控制自然feature() 开关控制,方便 A/B 测试和灰度发布从这份代码可以看出,Claude Code 本质上是一个精心设计的 AI Agent 框架,核心是一个带有工具调用、上下文管理、权限控制的对话循环。技术上没有什么黑魔法,但工程细节做得相当扎实。这个系统从 2024 年 8 月开始构建,目前已有超过 10 万开发者在使用,且代码几乎全部由 AI 生成。
这次泄漏的安全影响不止于 IP 暴露。AI 安全公司 Straiker 指出,攻击者现在可以研究数据在 Claude Code 内部上下文管道中的流转方式,精心构造能在上下文压缩后依然存活的 payload,实现跨会话持久化攻击。泄漏还暴露了从未公开的内部依赖包名,导致数小时内就出现了 npm typosquatting 攻击活动。
对所有发布 npm 包的开发者来说,这次事件的教训很直接:
# 发布前检查,有 .map 文件就中止
if find dist/ -name "*.map" | grep -q .; then
echo "ERROR: sourcemap files found. Aborting publish."
exit 1
fi或者在 package.json 里用白名单明确控制发布内容:
{
"files": [
"dist/**/*.js",
"dist/**/*.d.ts"
]
}一个遗漏的配置项,51 万行代码的代价。
参考资料:Cybernews[2] | The Register[3] | NDTV[4] | Medium @onix_react[5]
Content was rephrased for compliance with licensing restrictions.
[1] Ink: https://github.com/vadimdemedes/ink
[2] Cybernews: https://cybernews.com/security/anthropic-claude-code-source-leak
[3] The Register: https://www.theregister.com/2026/03/31/anthropic_claude_code_source_code/
[4] NDTV: https://www.ndtv.com/science/anthropics-ai-coding-tool-leaks-its-own-source-code-for-the-second-time-in-a-year-11291517
[5] Medium @onix_react: https://medium.com/@onix_react/claude-code-leak-d5871542e6e8