Claude Code 源码通过 source map 意外泄露,暴露了假工具的实现、复杂的正则匹配逻辑和隐藏的模式设计。
更新:见本文在 HN 的讨论:https://news.ycombinator.com/item?id=47586778
我每天都在用 Claude Code,所以当 Chaofan Shou 今早发现 Anthropic 在其 Claude Code npm 包中随附了一个 .map 文件,其中包含这个 CLI 工具的完整、可读源代码时,我立刻想深入研究。这个包此后被下架了,但不是在代码被广泛镜像之前,包括我自己也有镜像,并且在 Hacker News 上被拆解分析。
这是 Anthropic 一周内第二次意外泄露(模型规范泄露就在几天前),Twitter 上一些人开始想知道这是否有人故意为之。可能不是,但无论如何都不太好看。时间很难忽视:就在十天前,Anthropic 对 OpenCode 发起法律威胁,强制其移除内置的 Claude 身份验证,因为第三方工具正在使用 Claude Code 的内部 API 以订阅费率而非按令牌付费的方式访问 Opus。整个事件传奇使下面的某些发现更加引人注目。
所以我花了整个上午阅读 HN 评论和泄露的源代码。我把所有发现列在下面,大致按照我认为有多"爆炸性"的程度排列。
在 claude.ts(第 301-313 行),有一个名为 ANTI_DISTILLATION_CC 的标志。启用后,Claude Code 在其 API 请求中发送 anti_distillation: ['fake_tools']。这告诉服务器在系统提示中默默地注入虚假工具定义。
想法是:如果有人正在录制 Claude Code 的 API 流量来训练竞争对手的模型,虚假工具会污染该训练数据。它由 GrowthBook 功能标志(tengu_anti_distill_fake_tool_injection)把控,仅对第一方 CLI 会话有效。
这是人们在 HN 上首先注意到的事情之一。
betas.ts(第 279-298 行)还有第二个 anti-distillation 机制,服务端连接符文本摘要。启用后,API 在工具调用之间缓冲助手的文本,对其进行摘要,并返回带有密码学签名的摘要。在后续轮次中,原始文本可以从签名恢复。如果你在录制 API 流量,你只会获得摘要,而不是完整的推理链。
解决办法很容易。查看 claude.ts 中的激活逻辑,虚假工具注入需要所有四个条件都为真:ANTI_DISTILLATION_CC 编译时标志、cli 入口点、第一方 API 提供商,以及 GrowthBook 标志 tengu_anti_distill_fake_tool_injection 返回 true。一个 MITM 代理可以在请求到达 API 之前从请求体中剥离 anti_distillation 字段来绕过它,因为注入是服务端的且可选的。shouldIncludeFirstPartyOnlyBetas() 函数也会检查 CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS,所以将该环境变量设置为真值会禁用整个功能。如果你使用第三方 API 提供商或 SDK 入口点而不是 CLI,检查永远不会触发。连接符文本摘要的范围甚至更窄,仅限 Anthropic 内部(USER_TYPE === 'ant'),所以外部用户无论如何都不会遇到它。
任何认真打算从 Claude Code 流量中蒸馏的人都会在阅读源代码约一小时内找到这些解决办法。法律执行可能是真正的威慑。
undercover.ts 文件(约 90 行)实现了一种模式,当 Claude Code 在非内部仓库中使用时,会剥离所有 Anthropic 内部的痕迹。它指示模型永远不要提及内部代码名如"Capybara"或"Tengu"、内部 Slack 频道、仓库名称或短语"Claude Code"本身。
"There is NO force-OFF. This guards against model codename leaks."
你可以用 CLAUDE_CODE_UNDERCOVER=1 强制打开,但无法强制关闭。在外部构建中,整个函数被死代码消除到琐碎的返回。这是一扇单向门。
这意味着来自 Anthropic 员工在开源项目中的 AI 编写的提交和 PR 将没有迹象表明是 AI 编写的。隐藏内部代码名是合理的。AI 主动假装是人类是另一回事。
userPromptKeywords.ts 包含一个检测用户挫折感的正则表达式模式:
/\b(wtf|wth|ffs|omfg|shit(ty|tiest)?|dumbass|horrible|awful|
piss(ed|ing)? off|piece of (shit|crap|junk)|what the (fuck|hell)|
fucking? (broken|useless|terrible|awful|horrible)|fuck you|
screw (this|you)|so frustrating|this sucks|damn it)\b/
一个 LLM 公司使用正则表达式进行情感分析很有趣,但正则表达式比推理调用快得多也便宜得多,只是为了检查某人是否在骂你的工具。
在 system.ts(第 59-95 行),API 请求包含一个 cch=00000 占位符。在请求离开进程之前,Bun 的原生 HTTP 栈(用 Zig 编写)用计算的哈希值覆盖这五个零。服务器随后验证哈希以确认请求来自真实的 Claude Code 二进制文件,而不是伪造的。
他们使用相同长度的占位符,这样替换不会改变 Content-Length 标头或需要缓冲区重新分配。计算发生在 JavaScript 运行时之下,所以对 JS 层中运行的任何东西都是不可见的。基本上就是 HTTP 传输级别的 API 调用 DRM。
这是 OpenCode 法律争执背后的技术执行。Anthropic 超越了政策:二进制文件从密码学上证明它是真实的 Claude Code 客户端。如果你想知道为什么 OpenCode 社区在 Anthropic 的法律通知后不得不求助于会话拼接黑客和身份验证插件,这就是原因。
证明有漏洞。整个机制由编译时功能标志(NATIVE_CLIENT_ATTESTATION)把控,cch=00000 占位符仅在该标志打开时被注入到 x-anthropic-billing-header。标头本身可以通过将 CLAUDE_CODE_ATTRIBUTION_HEADER 设置为假值完全禁用,或通过 GrowthBook 杀死开关(tengu_attribution_header)远程禁用。Zig 级别的哈希替换也仅在官方 Bun 二进制文件内工作。如果你重新构建了 JS 包并在常规 Bun(或 Node)上运行它,占位符会原样保留:五个字面零到达服务器。服务器是完全拒绝它还是只是记录它是一个开放的问题,但代码注释引用了一个服务端 _parse_cc_header 函数,它"容许未知的额外字段",这表明验证可能比预期的 DRM 类系统更宽松。一个有决心的第三方客户端可能能够绕过它,尽管这需要一些努力。
autoCompact.ts(第 68-70 行)中的注释:
"BQ 2026-03-10: 1,279 sessions had 50+ consecutive failures (up to 3,272) in a single session, wasting ~250K API calls/day globally."
修复?MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3。在 3 次连续失败后,该会话的其余部分禁用压缩。三行代码就能停止每天浪费 25 万次 API 调用。
整个代码库中,都有对称为 KAIROS 的功能门控模式的引用。根据 main.tsx 中的代码路径,它看起来像一个未发布的自主 Agent 模式,包括:
一个用于"夜间记忆蒸馏"的 /dream 技能
每日仅附加日志
GitHub 网络钩子订阅
后台守护进程工作者
每 5 分钟 cron 计划刷新
这可能是泄露中最大的产品路线图细节。
实现受到严格把控,所以谁知道它进展了多远。但是一个始终运行、后台运行的 Agent 代码在那里。
明天是 4 月 1 日,源代码中包含几乎肯定是今年 April Fools' 笑话的内容:buddy/companion.ts 实现了一个 Tamagotchi 风格的伴侣系统。每个用户都会获得一个确定性的生物(18 种物种、从常见到传奇的稀有度等级、1% 的闪亮机会、DEBUGGING 和 SNARK 等 RPG 统计),通过 Mulberry32 PRNG 从他们的用户 ID 生成。物种名称用 String.fromCharCode() 编码以躲避构建系统的 grep 检查。
ink/screen.ts 和 ink/optimizer.ts 中的终端渲染借用了游戏引擎技术:一个 Int32Array 支持的 ASCII 字符池、位掩码编码的样式元数据、合并光标移动并取消隐藏/显示对的补丁优化器,以及自驱逐行宽缓存(源声称"在令牌流式传输期间 stringWidth 调用减少了约 50 倍")。当你记住这些东西一次流式一个令牌时,似乎有点过度。
每个 bash 命令都通过 bashSecurity.ts 中的 23 个编号的安全检查:18 个被阻止的 Zsh 内置、针对 Zsh 等号扩展的防御(=curl 绕过 curl 的权限检查)、unicode 零宽空间注入、IFS null 字节注入,以及在 HackerOne 审查期间发现的畸形令牌绕过。那是一个非常具体的 Zsh 威胁模型。
Prompt 缓存经济学显然驱动了许多架构。promptCacheBreakDetection.ts 跟踪 14 个缓存破坏向量,还有"粘性闩锁"防止模式切换破坏缓存。一个函数被标注为 DANGEROUS_uncachedSystemPromptSection()。当你为每个令牌付费时,缓存失效就是一个会计问题。
coordinatorMode.ts 中的多 Agent 协调有趣之处在于编排逻辑完全存在于一个提示中。它通过系统提示指令管理工作 Agent,如"Do not rubber-stamp weak work"和"You must understand findings before directing follow-up work. Never hand off understanding to another worker."
代码库也有一些粗糙的地方。print.ts 有 5,594 行,单个函数跨越 3,167 行和 12 个嵌套级别。他们使用 Axios 进行 HTTP,这与 Axios 刚在 npm 上被破坏并有恶意版本投放远程访问木马的时间很有趣。
有些人正在淡化这一点,因为 Google 的 Gemini CLI 和 OpenAI 的 Codex 已经是开源的。但那些公司选择开源一个 Agent SDK(一个工具包)。这是一个商业产品的完整源代码,被意外泄露。
代码可以重构。功能标志才是真正的问题:KAIROS、anti-distillation 机制。这些是竞争对手现在可以看到并为之计划的产品路线图细节。这是无法撤销的。
另外:Anthropic 在去年年底收购了 Bun,Claude Code 建立在其之上。一个 Bun 漏洞(oven-sh/bun#28001),在 3 月 11 日提交,报告源图在生产模式下也被提供,尽管 Bun 自己的文档说应该禁用它。这个问题仍未解决。如果这就是导致泄露的原因,那么 Anthropic 自己的工具链发布了一个已知漏洞,该漏洞暴露了他们自己产品的源代码。
正如一条 Twitter 回复所说的那样:"accidentally shipping your source map to npm is the kind of mistake that sounds impossible until you remember that a lot of the codebase was probably written by the AI you are shipping."