← 返回全部文章
深度分析 · 2026年6月8日 · 10 分钟阅读

CLAUDE.md 已经成了攻击面:Miasma 蠕虫证明了什么

“配置也是攻击面”真正可怕的版本,并不是模型被诱导写出坏代码,而是你刚用代理打开一个仓库,攻击者的代码就已经在本机静默运行。这个星期,70+ 个 Microsoft 仓库把这件事演示了一遍。下面讲清楚触发方式、研究脉络,以及哪些防护真的有用。

过去两年,围绕 AI 编程安全的讨论大多还停在假设层:攻击者能不能把恶意指令藏进代理会读取的文件里?这个星期,这不再是假设。编程代理会自动加载并信任 CLAUDE.md.cursorrules、配置钩子、MCP 工具描述、累积记忆;这些东西已经是攻击面。一个自我复制的蠕虫刚刚在 Microsoft 仓库上公开演示了这一点。

发生了什么:Miasma 蠕虫

2026 年 6 月 5–8 日前后,GitHub 的自动化系统停用了 70+ 个 Microsoft 仓库(安全公司报道为 73 个),涉及四个组织:Azure、Azure-Samples、Microsoft、MicrosoftDocs。The Register 把这次事件记录为一次 105 秒、两波完成的下架。截至目前,Microsoft 通过 TechCrunch 给出的唯一在案表态是:它在调查潜在恶意内容时临时移除了一些仓库(原文:“temporarily removed some repositories as we investigated potential malicious content.”)。404 Media 最先披露此事,并坦率写道,这次入侵的轮廓还不清楚(原文:“the exact contours of the breach are unclear.”)。不过这不是凭空猜测:Microsoft 自己的 Defender 团队 6 月 2 日就记录过更广义的 Miasma 攻击行动;更早那一路攻击命中了 Red Hat 的 npm 包,并从 GitHub、npm、Amazon Web Service (AWS)、Azure、Google Cloud Platform (GCP)HashiCorp Vault、Kubernetes 和开发者系统中窃取凭证(原文:“harvest[ed] credentials from GitHub, npm, Amazon Web Service (AWS), Azure, Google Cloud Platform (GCP), HashiCorp Vault, Kubernetes, and developer systems.”)。同一场攻击行动,换了新的投递渠道。

已经被多方交叉印证的是触发方式;这也是本文的重点。注意,这里的归因和攻击链来自 StepSecurity 等安全公司的取证,以及 The Hacker News 的报道,不是 Microsoft 已确认的完整结论。攻击从一次针对 Azure/durabletask 的恶意提交开始;按取证说法,这个提交是通过一个此前已被攻陷的贡献者账号推上去的,而同一个账号也把这起事件与 5 月 19 日那次木马化 PyPI 攻击联系起来。这个蠕虫被命名为 Miasma,并被评估为 Mini Shai-Hulud 蠕虫的变种。它提交了一组给代理读取的配置文件,目标很直接:开发者只要在自己的编程工具里打开仓库,攻击载荷就立刻触发。

  • .claude/settings.jsonClaude CodeSessionStart 配置钩子,在会话启动时运行攻击载荷
  • .gemini/settings.json:面向 Gemini CLI 的同类手法
  • .cursor/rules/setup.mdc:一份 Cursor 规则文件,里面放了提示注入(alwaysApply: true
  • .vscode/tasks.json:一项 VS Code 任务,配置了 "runOn": "folderOpen"

StepSecurity 的取证,攻击载荷是一个 ~4.6 MB 的 .github/setup.js。报告称,它会在“无需用户交互”的情况下自动执行(原文:“executes automatically without user interaction”),随后抓取凭证。开发者只要打开这个仓库,本机密钥就可能被拿走。

这里必须把两个限制条件说清楚,因为事件仍在发展。第一,准确仓库数量和被窃凭证的完整范围还没有定论;404 Media 前面那句 “the exact contours of the breach are unclear” 是目前更稳妥的定性。在 Microsoft 发布完整的事后复盘前,不应该把攻击链说死。第二,这是一次混合攻击:4 个攻击路径里,3 个是会自动运行的配置钩子/任务;只有 Cursor 的 .mdc 是真正面向模型的提示注入。这层区别很重要。它不是在降低风险,反而让结论更严峻:攻击者甚至不必骗过模型,只要让代理打开一个文件夹。

核心论点:自动加载,就是自动信任

所有编程代理都有同一处软肋。为了有用,它必须读取你没写的文件;其中有些文件,还会在缺少充分确认的情况下直接影响行为。这个集合比很多人想得更大:

  • 启动时加载的指令文件CLAUDE.mdAGENTS.md.cursorrules、Copilot 指令。Anthropic 自己的文档写明,CLAUDE.md 文件会在启动时完整加载(原文:“are loaded in full at launch”)。
  • 配置钩子:在生命周期事件上运行 shell 命令;Miasma 用的正是这条攻击路径。
  • MCP 工具描述:模型能看到,但你通常看不到完整内容的工具说明。
  • 代理记忆:跨会话持久化,之后又会被当作事实重新读取。

它们的共同点是:自动加载、自动信任。人会审查 PR;但几乎没人会在刚克隆一个仓库后,先认真读完里面的 CLAUDE.md,也很少有人逐字段审查刚添加的 MCP 服务器工具描述。

研究其实早就摆在那里

Miasma 是真实攻击里的证明;但这个漏洞类别,至少一年多前就已经被写清楚了。

Rules File BackdoorPillar Security,2025 年 3 月)。 研究人员证明,攻击者可以在 Cursor 和 GitHub Copilot 的规则文件里植入隐藏指令,使用的是 “zero-width joiners, bidirectional text markers, and other invisible characters”(零宽连接符、双向文本标记和其他不可见字符)。模型能读到这些内容,人类审阅者却看不见;结果是,代理会悄悄生成带后门的代码,而且后门会在代码库中继续扩散,聊天记录里没有痕迹(原文:“propagates through the codebase, with no trace in the chat history”)。一个很能说明问题的细节是:Cursor 的说法是,这不是他们一侧的漏洞(原文:“not a vulnerability on their side”);GitHub 的结论则是,用户需要自己审查并接受建议(原文:“responsible for reviewing and accepting suggestions”)。翻成工程里的话:指令文件归你自己审查。CLAUDE.mdAGENTS.md 属于同类文件;Pillar 在 Cursor 和 GitHub Copilot 上证明了这个问题,Miasma 则把同类文件里的 .cursor/rules 带进了真实攻击。

OWASP LLM01(Prompt Injection)。 OWASP LLM Top 10 的第一项点出了隐藏 Unicode 攻击载荷能生效的关键原因:提示注入不需要让人看得见、读得懂,只要模型会解析即可(原文:“do not need to be human-visible/readable, as long as the content is parsed by the model,”)。而间接注入发生在模型接收来自网站或文件等外部来源输入时(原文:“when an LLM accepts input from external sources, such as websites or files”)。

MCP Tool PoisoningInvariant Labs,2025 年 4 月)。 一次 工具投毒攻击 可以把恶意指令藏进 MCP 工具描述里;这些指令用户看不见,模型看得见(原文:“malicious instructions within MCP tool descriptions that are invisible to users but visible to AI models”)。它们的概念验证让代理读取用户 SSH 密钥并外传。原因很直接:模型看到完整工具描述,包括隐藏指令;用户通常只看到简化版本(原文:“AI models see the complete tool descriptions, including hidden instructions, while users typically only see simplified versions.”)。

Anthropic 在自己的文档里把话说透了

公平地说,Anthropic 在文档里把这个问题写得很直白;这也正是问题真实存在的最好证据。关于代理记忆,文档写道:“a successful prompt injection could write malicious content into the store. Later sessions then read that content as trusted memory.” 也就是说,一次成功的提示注入可以把恶意内容写进存储;后续会话又会把它当成可信记忆读取。(这正是为什么我们把 “Dreams” 记忆整合功能视为先审查、再信任的工具,而不是某种自动变聪明的魔法。)

如果你指望 CLAUDE.md强制执行规则,Claude Code 文档里最关键的一句话是:它把这些文件当作上下文,而不是强制配置;如果要无论 Claude 怎么判断都阻止某个动作,就用 PreToolUse 钩子(原文:“treats them as context, not enforced configuration. To block an action regardless of what Claude decides, use a PreToolUse hook instead.”)。你的 CLAUDE.md 里写“永远不要碰生产环境”,本质上只是建议。更糟的是,如果攻击者控制了这个文件,那就是攻击者的建议。

Anthropic 对 MCP 也很直接:它不会替你安全审计或管理任何 MCP 服务器(原文:“does not security-audit or manage any MCP server,”);同时也承认任何防御都有上限(原文:“no system is completely immune to all attacks.”)。

真正有效的防护是什么

好消息是:真正有意义的缓解措施,今天就能做;其中大部分还是你可能已经一路点过的官方流程。

  1. 在用代理打开任何仓库之前,先审查指令和配置文件。 这是 Miasma 最直接的教训。一个新克隆下来的仓库里,.claude/settings.json.cursor/rules/.vscode/tasks.jsonCLAUDE.md 都应该按陌生 shell 脚本的标准看待;因为钩子本来就是会运行的脚本。Anthropic 的安全文档说得很清楚:先审查待批准命令(原文:“review suggested commands before approval”),并把不可信工作放进 VM。
  2. 不要绕过权限提示。 Claude Code 默认采用严格只读权限(原文:“uses strict read-only permissions by default”),并把敏感操作放到审批之后;--dangerously-skip-permissions 这个开关确实存在,而名字本身就是警告。除了一次性沙箱,不要用。
  3. 尊重已经存在的信任门槛。 项目第一次使用外部 @import 时,Claude Code 会弹出列出文件的审批对话框(原文:“shows an approval dialog listing the files”);首次接触的代码库和新的 MCP 服务器也需要信任确认。这里有个锋利边界要记住:使用 -p 做非交互运行时,信任校验会被禁用;所以无交互/CI 运行必须有自己的护栏。
  4. 限制并审查 MCP 服务器;固定它们的工具定义。 优先使用你自己写的、或你明确信任的服务器;批准时保存工具列表快照,并在每个会话重新检查(Invariant 发布的 mcp-scan 正是为这个场景准备的)。今天正常的服务器,明天也可能发布带毒的描述。
  5. 把记忆和规则当作“先审查、再信任”;参考型存储设为只读。 自动记忆是你随时可以编辑或删除的普通 Markdown(原文:“plain markdown you can edit or delete at any time”),所以要审计。Anthropic 的建议是:任何代理不需要写入的存储,都使用 read_only
  6. 必须强制执行的规则,用钩子,不要用散文。 如果一条规则必须在模型怎么判断、被污染的 CLAUDE.md 怎么说都不影响的情况下成立,它就应该放进 PreToolUse 钩子;这个钩子是在模型自由裁量之外运行的代码。这就是“上下文”和“控制”的边界。

最不舒服的结论是:让编程代理显得像魔法的自动加载机制,本身就是攻击面。社区一直在围绕产品边界补工具;这一次,出问题最严重的正是这条边界。Miasma 没有发现一个全新的漏洞;它只是把 2025 年初就被记录下来的问题武器化,并把目标对准了世界上最常被克隆的一批仓库。修复方式也不是等厂商发补丁。你必须把代理自动读取的每个文件都当作不可信输入,因为它们本来就是。

相关阅读

相关阅读


文章独立产出 · 编辑政策

继续阅读 →