'No way to prevent this,' says only package manager where this regularly happens
449 points • 3 days agoArticle Link

npm registry 遭遇大规模供应链攻击,导致数百万企业级应用被入侵、数十亿用户记录泄露。 JavaScript 生态的开发者们反应如出一辙:这完全不可避免。高级前端工程师 Mark Vance 精准地捕捉到了这种心态,称这"只是构建现代 Web 应用的代价",这一观点在社区中广为认同。社区甚至会为像字符串大写这种基础任务,依赖由匿名陌生人维护的未经审查、层层嵌套的包。此次攻击利用了一个长期无人维护的工具包,在全球生产构建中注入了加密矿工,但开发者们仍把它归为不可预见的悲剧。

与此同时,Go 、 Rust 以及主要依赖原生 Web API 的生态系统报告为零事故,这得益于它们健全的标准库和内置于核心工具的严格加密验证。两者的对比突显出方法论上的关键差异:这些生态系统尽量减少对第三方代码的依赖,并把安全当作基础性考量,而不是事后补救。相比之下,npm 生态的默认行为仍是在本地机器上执行任意安装脚本,这一做法已多次导致灾难性后果。

一位 npm 发言人对受害者表示同情,但称即便 registry 存在已知漏洞,也没有任何 registry 策略或构建沙箱能阻止此次攻击。这番表态反映了 JavaScript 社区反复出现的模式:强调韧性胜过预防,把安全事件视为不可避免的自然灾害,而非系统性失误。在下一次事件到来之前,开发者们只能轮换 AWS 密钥、发发祈祷——这样的循环看来短期内难以打破。

217 comments • Comments Link

• 冷却期是防止 npm 供应链攻击的有效手段:大多数恶意包会在几小时内被发现,因此即便把新发布包的采纳延后一天,也能阻止入侵。 pnpm(已默认启用一天冷却期)、 depsguard 和 cooldowns.dev 等工具简化了这一做法,并提供了针对紧急安全补丁的绕过机制。

• 七天的冷却期看起来过长,但对项目初期会使用数月的依赖来说通常是安全的,只有在应对已知漏洞时才应进行显式的即时升级。

• Maven Central 的做法值得 npm 借鉴:要求验证命名空间所有权(例如通过域名控制)、强制已发布包不可变,并避免使用动态版本范围。与 npm 较宽松的策略相比,这些措施能降低供应链风险。

• JavaScript 生态中大量小而深度交织的依赖使严格锁定版本变得不切实际,这与 Java 的单体库不同,因此其他生态系统的解决方案难以直接移植到 JavaScript 。

• 安装后脚本是 npm 的主要攻击面之一:它们在安装时以安装程序的权限自动运行,常在持有敏感令牌的 CI/CD 环境中执行,使恶意代码能够像蠕虫一样快速扩散——最近的 Shai-Hulud 攻击就是例证。

• 广义上讲,安装后脚本只是一个加速器——毕竟依赖中的代码总有机会被执行——但它们显著缩短了防御者的反应时间,比起只在运行时或测试时触发的负载更难防范。

• Rust 和 Go 也并非固若金汤;尽管它们的依赖平均较少,但 build.rs 等构建脚本和 go:generate 等代码生成机制仍可能执行不受信任的代码,而且这些生态缺乏强力的沙箱或强制性安全策略。

• 所有生态系统面临的根本问题是经济层面:像软件包注册表和核心库这样关键的基础设施服务数十亿用户,却长期资金不足,导致在命名空间验证或自动扫描等基本安全措施上的投入微乎其微。

• 文化因素也在加剧问题:习惯性地频繁更新依赖、维护者为显得活跃而做不必要的变更,以及对依赖审计重视不够,这些都增加了供应链风险暴露。

• 使用 Nix 管理依赖或改用默认禁用安装后脚本的包管理器等替代方案能提供有效防护,但要实现系统性改进,还需要更好的工具以及开发者行为和资金模式的变化。

讨论达成的共识是:虽然冷却期、锁定文件和禁用安装后脚本等技术缓解措施能降低风险,但潜在漏洞源于开源生态和资金维护方式中的结构性缺陷。没有任何单一方案可以彻底杜绝供应链攻击,必须采取纵深防御——工具、策略与文化变革相结合。关于某些生态(如 npm)是否存在独特缺陷,还是仅因其规模与集中性而更易成为目标,争论仍在进行;参与者提醒不要自满,也不要将责任归咎于单一因素。