2026 年 3 月 31 日,Anthropic 在发布 Claude Code npm 包时因配置失误,将调试用的 source map 文件一同打包发布,导致完整的 TypeScript 源码意外暴露。这一看似简单的配置错误,却为安全研究者与开发者提供了一次难得的内部架构观察机会。通过逆向分析泄露的源码,我们可以深入理解这款 AI 编程助手的核心实现机制,从中获取工程实践的有益参考。

泄露事件的本质与影响范围

此次泄露的核心是一个约 57 MB 的 source map 文件,它被错误地包含在公开发布的 npm 包中。source map 是现代前端构建流程中的常见产物,其作用是将压缩后的生产代码映射回原始源代码,便于开发者调试。然而,当这类调试文件被发布到生产环境时,任何人都可以借此还原完整的源码结构。

泄露的内容覆盖了 Claude Code CLI 的数千个文件,涵盖了从工具定义、权限模型到系统提示词的完整实现。需要明确的是,这次泄露并不涉及模型权重、训练数据或核心 AI 推理基础设施 —— 暴露的仅是客户端工具链代码。这意味着研究者观察到的主要是「如何使用模型」而非「模型本身如何工作」。尽管如此,对于理解一个生产级 AI 编程工具的工程架构,这些信息已经足够丰富。

从技术团队的角度,这次事件最直接的教训在于构建流程中的文件过滤机制不完善。在 npm 包发布前,应当通过 .npmignore 或 package.json 的 files 字段明确排除 *.map 等调试产物,并在持续集成流程中加入预发布审计步骤,验证最终打包内容是否包含预期之外的文件。

系统提示词的层次化设计

通过 mitmproxy 捕获的网络流量分析,Claude Code 展现出一种高度结构化的系统提示词设计思路。整体架构分为三个主要层次,每个层次承担不同的职责。

第一层是新话题检测。当用户输入任何内容时,系统首先会通过一个轻量级的判断流程分析当前输入是否开启了一个新的对话主题。如果是,系统会从输入中提取一个仅包含两到三个关键词的标题,用于后续上下文管理。这一判断通过向模型发送专门的提示词完成,返回结构化的 JSON 格式结果。这种设计确保了对话上下文的精确划分,避免了多主题混杂导致的上下文污染。

第二层是完整的系统指令包装。确认新话题后,用户的输入会被嵌入到一个详细的系统提示词框架中。这个框架明确声明了 Claude Code 的身份定位 ——Anthropic 官方 CLI 工具,并给出了关于响应风格的具体约束。值得注意的是,系统提示词特别强调「简洁直接」,要求模型避免冗长的铺垫和解释,一词回答是最理想的状态。这一设计直接反映了 CLI 场景的特殊性:终端用户的注意力资源有限,过度的自然语言包装会干扰信息获取效率。

第三层是上下文信息的结构化注入。系统提示词中包含了当前工作环境的完整快照,包括工作目录路径、是否为 Git 仓库、操作系统平台、当前日期等基础信息。更关键的是,它还会嵌入项目目录的完整树形结构,以及 Git 状态快照。这些信息使得模型能够在充分了解项目状态的前提下做出决策,而非在真空中进行推理。

工具调用的代理机制

Claude Code 的工具系统采用了分层代理架构,这种设计在保证灵活性的同时实现了权限的精细管控。通过分析泄露代码中的工具定义部分,研究者发现了十一项核心工具的完整描述。

主代理通过 dispatch_agent 工具启动子代理,这是一个关键的设计决策。子代理拥有独立的工具集,限制为 ViewGlobToolGrepToolLSReadNotebookWebFetchTool 六项。这种工具集的收窄意味着主代理可以将搜索类任务委派给子代理,而子代理无法执行文件写入或命令执行等高风险操作,形成了天然的安全边界。

批量执行工具 BatchTool 体现了对效率的追求。当代理需要同时获取多个文件的上下文时,它可以一次性发起多个工具调用请求。系统会尝试并行执行这些调用以减少往返延迟,只有在存在依赖关系时才退化为串行处理。对于需要收集项目结构的场景(如 /init 命令),这种批量机制显著降低了_token 消耗和响应延迟。

文件操作工具的命名也值得玩味。Claude Code 提供了 EditReplaceWrite 三个层级的写入工具,它们对应不同的使用场景和风险级别。Write 是完全覆盖式写入,Edit 应该是精细化的代码修改,而 Replace 则可能是两者的折中。这种细分体现了对不同编辑场景的深入理解 —— 并非所有文件操作都需要完整的上下文覆盖,有时候精确的片段修改更为高效。

Bash 命令的安全策略

通过逆向分析,研究者发现 Claude Code 在执行 Bash 命令前部署了一套完整的安全检测流程。这一流程的核心是命令前缀提取与风险分类系统。

当用户输入一个需要执行的 Bash 命令时,系统会首先调用专门的模型来判断该命令的前缀。所谓的「前缀」,指的是命令的核心动作部分,例如 git commit -m "foo" 的前缀是 git commitfind ./src -type f -name "*.ts" 的前缀是 find。这个设计允许用户预先定义允许执行的命令类别,系统只需验证实际执行的命令是否落入已授权的前缀范围。

更值得关注的是命令注入检测。当模型分析用户输入时,如果发现存在命令注入的风险特征 —— 例如 git status 后面跟着反引号执行的额外命令 ls,或者使用了 $() 子 shell 语法 —— 系统会立即标记为 command_injection_detected。这种检测机制的存在,使得即便用户误以为已授权某个命令前缀,恶意构造的注入语句也会触发额外的确认流程。

在实际的 UX 流程中,每次 Bash 调用都需要经过两轮模型调用:第一轮确定命令前缀和安全风险,第二轮提取命令实际访问的文件路径。这种设计虽然增加了_token 消耗和响应延迟,但为用户提供了可解释的安全保障 —— 用户能够清晰看到系统是如何理解和批准每一个命令的。

上下文管理的工程实践

Claude Code 的上下文管理策略体现了对 token 成本与推理质量之间平衡的深入思考。项目目录结构的快照是静态的 —— 它只在会话开始时生成一次,随后不会随文件变化而更新。这一设计选择背后的逻辑是:频繁更新完整的目录结构会导致上下文快速膨胀,而大部分工具调用实际上只需要局部信息。

Git 状态的嵌入同样采用了快照模式。用户可以看到当前分支、未提交的修改、已删除和未跟踪的文件列表,但这些信息不会在每次操作后自动刷新。这种设计确保了对话开始时的上下文在整个会话期间保持稳定,避免了模型因信息频繁变化而产生不一致的推理。

一个有趣的细节是系统使用了不同能力的模型来处理不同复杂度的任务。根据逆向观察,Claude Code 在需要深度推理的场景使用 claude-3-7-sonnet,而在简单判断任务(如解析 Bash 命令前缀)中使用 claude-3-5-haiku。这种模型路由策略能够在保证输出质量的同时显著降低成本 —— 简单任务用小模型处理即可,无需动用最强大的推理模型。

对开发者的启示

从 Claude Code 的架构设计中,我们可以提炼出若干对构建自研 AI 工具的实践建议。首先,系统提示词的分层设计值得借鉴:将话题判断、身份声明、上下文注入划分为独立的处理阶段,使得每个阶段的提示词可以独立优化和测试。

其次,工具权限的层级控制是保障安全的关键。即便是同一类型的工具,也应当根据风险级别进行细分,并为子代理提供受限的工具集。这不仅是安全考量,也是一种工程上的关注点分离 —— 让不同的代理各司其职,降低系统的整体复杂度。

第三,预设的安全机制应当对用户保持透明。Claude Code 的命令前缀检测和文件路径提取都是用户可见的,用户能够理解系统为何要求确认某个命令。这种可解释性对于建立用户信任至关重要,尤其是在处理高风险操作时。

最后,对于所有发布 npm 包的团队,这次事件再次提醒我们:调试产物与生产代码的分离应当成为标准流程的一部分。在持续集成中加入包内容审计步骤,使用 .npmignore 或 files 字段明确排除 .map、.debug 等文件,能够有效避免类似的信息泄露。


资料来源:本文技术细节主要基于 Kir Shatrov 的逆向工程分析(kirshatrov.com/posts/claude-code-internals),以及安全社区对 2026 年 3 月 source map 泄露事件的公开报道。