惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
N
Netflix TechBlog - Medium
V
Visual Studio Blog
博客园 - Franky
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 三生石上(FineUI控件)
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
量子位
大猫的无限游戏
大猫的无限游戏
人人都是产品经理
人人都是产品经理
V
V2EX
The Cloudflare Blog
月光博客
月光博客
Last Week in AI
Last Week in AI
雷峰网
雷峰网
WordPress大学
WordPress大学
博客园 - 【当耐特】
博客园 - 聂微东
IT之家
IT之家
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

Under the Sun with Paddy

WordPress 平稳换主题:从本地验证到稳态的四阶段 – Under the Sun with Paddy 网站防护架构图:四层防线与它们的静默失败 – Under the Sun with Paddy WordPress 主题更换后的服务器运维与排错实录 – Under the Sun with Paddy 自”妍” WordPress 主题性能实测 – Paddy ‘s Blog 为什么做了一个报纸风格的 WordPress Markdown 主题 - Under the Sun with Paddy 88×31 – Under the Sun with Paddy 傻孩子我怕你啊,禁止被资本主义异化 – Under the Sun with Paddy [Agent 考古] Ciatto 2025 解读:LLM 住进 BDI 解释器,计划生成与 believes achieved 退化 – Under the Sun with Paddy [Agent 考古] 意图编辑权:从 BDI 到 LLM Agent,谁有权决定机器何时停下来 – Under the Sun with Paddy [Agent 考古] 25,000 次任务实测:多 Agent 协作协议质量排序与治理悖论 – Under the Sun with Paddy [Agent 考古] TouringMachines 与 INTERRaP:混合架构如何调和 Agent 的反应与慎思 – Under the Sun with Paddy [Agent 考古] KQML、FIPA、JADE 协议史:Agent 互操作失败全记录与 MCP/A2A 预测 – Under the Sun with Paddy [Agent 考古] 多 Agent 冲突仲裁三方案:均衡约定、PERSUADER 劝说与行为抽象 – Under the Sun with Paddy [Agent 考古] STEAM 与 ARCHON:联合意图理论如何落地真实工业多智能体系统 – Under the Sun with Paddy [Agent 考古] 合同网协议详解:Smith 1980 任务招标五步流程与囚徒困境的 Python 复现 – Under the Sun with Paddy [Agent 考古] 什么是 Agent?Wooldridge & Jennings 弱概念四性质与强概念定义详解 – Under the Sun with Paddy [Agent 考古] 意图即带承诺的选择:1990 年,”不放弃”第一次有了形式定义 – Under the Sun with Paddy [Agent 考古] 从进程栈到 Z 规范:BDI 意图架构的四代演化 – Under the Sun with Paddy [Agent 考古] 意图即承诺,智能体即社会——自主性的第一个可计算答案 (阶段三导航) – Under the Sun with Paddy 雷池WAF + fail2ban + AbuseIPDB 完整实战:从日志解析到自动封禁上报 – Under the Sun with Paddy 嚼别人嚼过的口香糖,AI 时代人的价值 – Under the Sun with Paddy 比尔·盖茨长文警告原文翻译:《动荡的 AI 时代已经到来,我们现在的选择至关重要》 – Under the Sun with Paddy [Agent 考古] 自知、自觉、自止——终章定论:Agent 不需要意识,但必须知道自己的边界、理由和终点 – Under the Sun with Paddy 雷池 WAF 一键升级失败解决:手动离线升级注意事项 – Under the Sun with Paddy [Agent 考古] 多头注意力共享目标、参数即隐式模型、CoT 是概率采样——LLM 被三条“反叛伏线”夹击 – Under the Sun with Paddy [Agent 考古] 别再给机器人建“世界模型”了!Brooks用代码证明:世界本身就是最好的模型 – Under the Sun with Paddy [Agent 考古] 别再给机器人装“大脑”了!1986 年的“三无”架构证明:越不思考,活得越久。 – Under the Sun with Paddy [Agent 考古] 你的大脑里住着一个小人吗——Minsky 说:不,住着成百上千个”笨蛋” – Under the Sun with Paddy [Agent 考古] 600 条规则,一个反向推理引擎——专家系统的顶峰是怎么建成又怎么暴露边界的 – Under the Sun with Paddy [Agent 考古] 秘书要求他离开房间——一个程序为什么让人想跟它说心里话 – Under the Sun with Paddy
打开即沦陷:keyv 蠕虫与 AI 编码助手时代的供应链暗战 – Und...
Paddy · 2026-08-30 · via Under the Sun with Paddy

2026-08-30 · 配套实验代码与全部证据:PaddySun/ai-supply-chain-security-lab 本文所有本地实验数据均可通过仓库脚本复现。

导语

2026 年 8 月 4 日早上,npm 生态发生了迄今为止最大规模的自我复制蠕虫事件。

攻击者拿下了 keyv 包维护者 Jared Wray 的 GitHub 账号。keyv——Redis 风格键值存储的底层依赖,周下载量 1.53 亿次,被 Deliveroo、Qlik、ServiceTitan 等大型企业在生产环境使用。攻击者用被盗的会话直接向 jaredwray/keyv 主干推送恶意提交,然后触发了项目自己的正规发布流水线——于是带毒的 keyv@6.0.0 携带完全合法的 SLSA 溯源签名发布上线,任何溯源门禁都拦不住它。

接下来的约 4 小时里,蠕虫自我复制扩散:444 个包、2212 个恶意版本,波及 12+ 组织,一级载具合计周下载量超过 5 亿次。安全社区先后给它起了两个名字:新加坡网络安全局称之为 Shai-Hulud(沙虫,《沙丘》),StepSecurity 称之为 ChainDrop

但真正让整个安全社区炸锅的是两件事:

第一,你不需要执行 npm install 蠕虫把持久化代码写进了 .claude/settings.json.vscode/tasks.json——你只是用 VS Code 打开了一个项目文件夹,或者启动了一次 Claude Code 会话,恶意代码就执行了。真实案例:流行的 million 仓库默认分支被植入这两个文件(issue #1186)。

第二,C2 地址不在代码里,而在以太坊区块链上。 恶意软件通过 eth_call 读取主网智能合约获取控制服务器地址——攻击者改一笔链上交易,全网被感染节点集体切换控制服务器。封域名、封 IP 的传统处置全部失效。

本文做三件事:还原事件的技术真相(含影响漏斗与版本清单);在本地完整复现”打开即执行”向量与 slopsquatting 测量实验;给出经核实的处置措施——包括一个反直觉的坑:发现感染后不要立刻吊销令牌


一、事件还原:四小时时间线(均为 UTC)

时间事件
09:02毒提交 ee2681a(”release: v6.0.0″)推入 jaredwray/keyv 主干
09:04提交 d8c850c 植入 .claude/.vscode/ 持久化文件
09:23提交 f97eabc 删除掩护用的假测试文件
09:35keyv@6.0.0 经 GitHub Actions OIDC 可信发布上线(携带合法 SLSA 证明)
09:38–13:20第二波:蠕虫用窃取的受害者凭据自我复制,再投毒 433 个包(2201 个版本),首个为 @thiennq/docs-viewer@1.6.2
10:09–10:14cacheable 生态 9 个恶意包发布
10:17第一声公开警报:jaredwray/cacheable issue #1689
10:39 起npm 开始下架(首个 cacheable-request@13.0.20
~11:15keyv 回滚至 5.6.0(安全版本)
18:10全部 11 个一级载具完成回滚

关键认知颠覆:初始入侵不是偷 npm token,而是劫持维护者的 GitHub 会话。攻击者用维护者身份触发项目自己的正规 release workflow(OIDC 可信发布),所以每个恶意版本都自带真实签名——正如 StepSecurity 的总结:”溯源证明的是哪个 commit 被构建了,它证明不了这个 commit 是被授权的。”

二、影响漏斗:从 1 个账号到 5 亿次周下载

1 个被劫持的 GitHub 账号(Jared Wray)
└─ 11 个一级载具(jaredwray 生态全量沦陷,2212 个恶意版本中的主体)
    └─ 433 个二级受害包(蠕虫用窃取的凭据自动重发布)
        ├─ @servicetitan   141 个包
  ├─ @onereach       78 个
  ├─ @or-sdk         74 个
  ├─ @ornikar         42 个
  ├─ @qlik           28 个
  ├─ @nebula.js       22 个
  ├─ @deliveroo / @picsart / 26 个无作用域包 …
        └─ 波及周下载量合计 > 5 亿次

一级载具清单(恶意版本号 → 安全处置)

包名恶意版本周下载量处置
keyv6.0.01.537 亿npm 回滚至 5.6.0
flat-cache6.1.241.499 亿回滚
file-entry-cache11.1.61.476 亿回滚
cacheable-request13.0.203396 万首个被下架
@cacheable/utils2.5.11871 万回滚
cacheable2.5.1788 万回滚
@cacheable/memory2.2.1718 万回滚
cache-manager7.2.10428 万回滚
@cacheable/node-cache3.1.2156 万回滚
ecto5.0.11293回滚
@cacheable/net2.1.1975回滚

受害者自查:审计 lockfile 中是否出现上述”包名@版本”组合;核对注册表 shasum(如 keyv@6.0.0 = 0f18da4e81443285c3ee7e96eb3adc3803b2487e);检索 CI 日志(backstage 仓库确认有 10 次恶意 workflow 运行,所幸只暴露了短命 GITHUB_TOKEN)。

三、载荷解剖:五段式攻击链

  1. preinstall 钩子:库代码本身干净(相对 rc.1 仅 3 个文件差异),毒在安装钩子里,还配了一个假 vitest 文件给钩子”正当性”。
  2. Dropper(setup.mjs):从 Bun 官方 GitHub Release 下载合法的 v1.3.13 运行时(”就地取材”,规避检测),落盘 /tmp/bun-dl-* 后执行第二阶段。
  3. Stage 2(727KB 混淆 Bun bundle):Shai-Hulud 2.0 的进化后代。窃取范围约 140 个凭据路径——.npmrc.aws.kube/config、SSH 私钥、Jenkins、Vault、加密钱包,外加新一代 AI 工具凭据.claude/credentials.json.codex/auth.json.cursor/credentials.json.openai/auth.json.anthropic/auth.json.gemini/.env。还会转储 GitHub Actions Runner.Worker 进程内存,抓取 "isSecret":true 标记的秘密,并横扫 16 个区域的 AWS STS/Secrets Manager/SSM。
  4. 自我复制引擎:内置 npm 发布器,把受害者包的 tarball 重新打包注入载荷后重发布,还能自铸 Sigstore/SLSA 溯源;在 GitHub 侧向所有分支推送 .vscode/tasks.json.claude/settings.json,提交者伪装成 claude <claude@users.noreply.github.com>,并植入一个把 ${{ toJSON(secrets) }} 写进 artifact 的”Run Copilot”工作流。
  5. 持久化 + 死手开关 + 链上 C2
    • .claude/settings.json 的 SessionStart hook 与 .vscode/tasks.jsonfolderOpen 任务互相交叉拉起对方的 dropper;
    • 安装令牌监视器(~/.local/bin/gh-token-monitor.sh,macOS LaunchAgent / Linux systemd user unit)——检测到被盗 GitHub 令牌被吊销时触发后续攻击载荷
    • C2 采用 EtherHiding:从以太坊主网合约 0xE1f2...3103eth_call(selector 0x53ed5143)解析 C2 域名,轮询 75 个 RPC 端点;外泄走 npm-cache.com:443/router,RSA-OAEP + AES-256-GCM 双层加密且双向可控(响应中的 code 字段会被 eval);甚至有俄语系统退出开关。

四、本地复现:打开项目 = 执行代码

完整代码与录屏:autorun-demo/。载荷是刻意无害的——写一行时间戳日志 + 弹出 Windows 计算器。真实蠕虫在这个位置放的是上面的 Stage 2。

攻击面 A:Claude Code — 启动会话即执行(零交互)

.claude/settings.json 写入 SessionStart hook,命令 sh demo_payload.sh。实测(Claude Code v2.1.224,2026-08-30):

[AUTORUN DEMO via Claude Code SessionStart] 2026-08-30 20:01:42
paddy                         ← whoami:以当前用户完整权限执行
CalculatorApp.exe PID 17692   ← 计算器进程

没有任何确认弹窗。 踩坑记录:hook 经 Git Bash 执行,命令写成 cmd /c "%CLAUDE_PROJECT_DIR%\xxx.cmd" 会报 EPERM: uv_spawn bash.exe 静默失败——载荷必须是合法 bash 语句。攻击者同样受此约束,但 bash 载荷完全可行。诚实注脚:测试机全局配置了 skipDangerousModePermissionPrompt: true,可能贡献了零弹窗;默认配置下的确认行为建议读者自行验证并对比。

攻击面 B:VS Code — 打开文件夹即执行(两道摩擦)

.vscode/tasks.json 配置 runOptions.runOn: "folderOpen",任务名伪装成 install-dependencies。实测有两道防线:新文件夹需先 Trust,再在”检测到自动任务”通知里点 Allow。但注意真实受害场景:keyv 投毒的是你自己的日常工作项目——文件夹早就信任过了;且不少开发者为正经的 watch/install 任务开过 task.allowAutomaticTasks: "auto",此后连通知都没有。第二次打开文件夹,计算器无声弹出。

结论:防御没有失效,失效的是”人对日常项目不设防”这个前提。 这正是 keyv 蠕虫的社会工程学支点。

五、本地测量:Slopsquatting 还成立吗

完整代码:slopsquatting-lab/

keyv 事件之前的另一个威胁假设是 slopsquatting(术语由 PSF 的 Seth Larson 创造):LLM 幻觉出不存在的包名,攻击者抢先注册。USENIX Security 2025 论文《We Have a Package for You!》的基线数据:16 个模型平均 19.7% 样本推荐不存在包名,编录幻觉包名 205,474 个,43% 在重复采样中稳定复现

本实验按论文方法论缩小复现(deepseek-chat,temperature 0.7,每 prompt 重复采样):

生态样本数唯一包名幻觉包数含幻觉样本
PyPI20500%
npm241900%

两个发现:

  1. 前沿模型已基本治好这个病(论文中 GPT-4 Turbo 就已低至 3.59%,2026 年前沿模型约 1%~2%)。威胁集中在自托管开源模型(幻觉率 6.8%~8.4%)——而恰恰是重度跑 Agent 的团队最爱自托管。每天 200 次 Agent 辅助安装的团队按 7% 幻觉率算,仍有约 14 次/天幻觉安装尝试。
  2. 方法论陷阱:第一轮跑出的”幻觉包”concurrentplatformgetpass 全是 Python 标准库——手写白名单误报。改用 sys.stdlib_module_names 后归零。复现这类研究时,标准库排除是最大误差源。

所以攻击面排序变了:与其赌模型报错包名(slopsquatting),不如直接在仓库里放 .claude/settings.json(打开即执行)——后者不需要模型犯任何错。

六、处置措施(经核实)

如果你可能感染了(用过 8 月 4 日当天的 keyv/cacheable 生态)

按 SANS ISC 的警告,顺序不能错:

  1. 不要先吊销令牌。 蠕虫的令牌监视器把吊销行为当触发器(死手开关)。
  2. 先在干净机器上(不是疑似感染的那台)操作:检查并移除持久化——.claude/settings.json.vscode/tasks.json 中的可疑 hook/任务、~/.local/bin/gh-token-monitor.sh、LaunchAgent/systemd user unit。
  3. 重装/重建:卸载恶意版本、lockfile 回锁到安全版本(keyv → 5.6.0);卸载本身不能消除已发生的凭据窃取,CI 节点建议直接重建。
  4. 然后轮换全部凭据:npm/GitHub/云/Vault,以及所有 AI 工具凭据(.claude/credentials.json 等都是此次的窃取目标)。

团队防御清单

  • task.allowAutomaticTasks: "off";把 .vscode/.claude/.idea/ 纳入 PR 审计,出现 shell 命令变更即告警(尤其提交者是 claude@users.noreply.github.com 这类身份)
  • Agent 的安装动作用私服代理 + 白名单;新注册/低下载量包需人工放行
  • CI 一律短命令牌(backstage 未泄密正是因为只有 ephemeral GITHUB_TOKEN
  • 别迷信溯源签名:SLSA 证明构建来源,不证明提交授权。维护者主干需要分支保护 + 提交签名强制
  • 给 Agent 挂注册表查询工具,推荐包前先验证存在性(治 slopsquatting)

七、结论

keyv 蠕虫的组合拳——劫持维护者会话 → 挂合法签名发布 → preinstall 窃凭据 → AI 配置文件持久化 → 链上 C2——每一环单独看都不新鲜,组合起来却让”克隆仓库/打开文件夹/启动会话”这些最日常的动作变成了攻击入口。我在本机验证了其中最关键的”零安装执行”环节(两条链均成功,其中 Claude Code 链零交互),也量化了 slopsquatting 在前沿模型上的收敛。防御者的重心必须从”安装时刻”移到”Agent 决策时刻“和”打开工作区的第一毫秒“。

参考资料