11 行代码的小包被删,半个前端世界一起断:left-pad 事件
目录
配图:AI 生成的概念示意图,非论文原图、真实现场或实验数据。
TL;DR:2016 年 3 月 22 日,开发者 Azer Koçulu 因包名纠纷撤下了自己发布在 npm 上的 273 个包,其中包括只有十来行代码的 left-pad。依赖它的项目(包括 Babel 等)随即构建失败,npm 最终从备份恢复了旧版本,故障持续约 2.5 小时。它不是黑客攻击,也不是 left-pad 本身有漏洞,而是依赖链的脆弱性被一次撤包放大了。
这是十年前的旧事:事件发生在 2016 年 3 月,并非最近的新闻。
一场包名之争
起因是名为 kik 的包。Azer 发布了这个包,而同名的即时通讯应用 Kik 的公司也想要这个名字,双方协商无果。Kik 向 npm 求助后,npm 按包名争议政策裁定 Kik 应当持有这个名字,并通知了双方。
一次没有预警的撤包
3 月 22 日(周二),Azer 没有通知任何下游项目,就把 kik 和另外 272 个包全部从 npm 撤下,总共 273 个。left-pad 是其中之一,它的功能只是给字符串左侧补齐字符,据报道最终版本去掉空行后只有 11 行代码。
问题在于它被大量项目间接依赖。太平洋时间下午 2:30 之后不久,npm 就看到每分钟数百次的失败请求。依赖链层层向上,Babel 等项目都因此无法正常构建或安装。
两个半小时的补救
十分钟内,Cameron Westland 就发布了一个功能相同的 left-pad 1.0.0。但错误并未停止:有些依赖链(例如 Babel 经由 line-numbers 的路径)明确要求 0.0.3 版本。npm 于是与 Cameron 合作,从备份重新发布了原版 0.0.3,下午 4:05 宣布计划,4:55 完成,整个中断约 2.5 小时。其他被撤的包也很快有社区成员发布分叉或占位包接手。
为什么值得记住
npm 在事后的说明中承认,不受限制的撤包会严重破坏对开源生态的信任,自己的沟通和响应也太慢。它同时坚持包名争议政策本身没有问题,认为造成故障的是突然撤包这个动作。
后续措施包括:让会破坏其他包的撤包更难进行;对已被完全撤下且有依赖者的包,发布占位包以防止名字被立刻抢注;改进内部政策以更好处理社区冲突。
这件事常被当作一个提醒:一个看起来微不足道的小依赖,可能是整条构建链上的单点故障。
来源:npm blog:kik, left-pad, and npm;交叉参考:Wikipedia:npm left-pad incident