刚输一行代码就报5次假漏洞,npm让程序员们累觉不爱

这或许也是CVE的问题

明敏 发自 凹非寺
量子位 报道 | 公众号 QbitAI

有这样一个命令,它可以帮助开发人员分析复杂的代码、查明特定漏洞。

哇,这是什么好东西,快来试试!

然而,当你真的开始执行这个命令时,却发现这事不对味了

它怎么老是报错啊?

甚至从项目刚开始创建时就报错,一路报到你自闭。

更可怕的是,这些报错的漏洞还都是假漏洞

这就是npm audit,它是npm v6中新增的一个命令。

本来想化身程序员的贴心小助手,结果因为总是“乱报错”却变得饱受诟病。

最近,一位程序员小哥实在忍无可忍,发帖直指npm audit的设计存在大问题,在网上引起了大家的广泛关注和讨论。

这个话题在Reddit上发布仅仅11小时,热度就飙升到459。

Hacker News上也得到了700+的关注。

网友们纷纷表示这些“漏洞”太荒谬了。

npm audit不能理解代码的上下文,也不懂程序员。

有网友晒出自己之前的血泪史:

我之前创建一个项目,它告诉我有97个漏洞(85个中等漏洞,12个高危漏洞)……

也有人指出,这种乱报错的现象恐怕要从不合理的CVE流程上说起…

所以,npm audit的问题到底出在哪?

过度报错令人头大

发帖吐槽的程序员小哥用一个非常生动形象的比喻指出了问题的关键。

npm audit就像是狼来了中的小孩,而开发人员就是那些被小孩戏耍的人。

理论上,使用npm audit后,它会分析代码然后找出漏洞。

比如,你的Node.js应用程序有一个依赖树。

现在在network-utility@1.0.0中存在一个漏洞。

这个漏洞在首次被发现后,将会发布在一个漏洞表中,下次运行npm audit时,npm将访问这个表。

发现漏洞后,npm audit会标出漏洞的数量和严重程度,然后可以执行下一步命令进行修复。

现在来执行npm audit fix,npm就会尝试安装最新的network utiltiy@1.0.1来修复漏洞。

只要database-layer指定它不完全依赖network-utility@1.0.0,在一些允许范围内允许1.0.1, 然后就能修复成功了:

如果database-layer@1.0.0完全依赖network-utility@1.0.0;这种情况下就需要database-layer有新版本允许network-utility@1.0.1:

如果还是没能修复,还可以尝试npm audit fix — force。

看上去,这个流程完全没毛病啊。

但是放在实际应用中,就完全不是这样了!

小哥用Create React App来做了个测试。

Create React App通过获取JavaScript源代码,再将其转化为静态HTML+JS+CSS文件夹。

结果,刚输入创建项目的代码,就出现了报错。

而且居然有5个!其中2个还是高风险。

这是哪个程序员能承受的住的啊!

事不宜迟,赶紧执行npm audit看看哪里出了问题。

先看第一个“漏洞”:正则表达式拒绝服务 (ReDoS)。

从报错中可以看到,漏洞存在于browserslist上。

这是用来做什么的呢?

Create React App可以生成针对你的目标浏览器优化的CSS文件,比如,你可以用它把目标现代浏览器放到package.json中:

由于多个工具依赖于目标浏览器的相同配置格式,因此Create React App使用共享browserslist包来解析配置文件。

所以这里的漏洞是什么?

正则表达式拒绝服务是指browserslist 中有一个正则表达式,这意味着如果有人恶意输入,那当字符串传递给browserslist 时,运行速度将会指数级降低。

这听起来真的非常糟糕,是个大漏洞。

但问题是,如果都有人能访问你的电脑并更改配置文件了,那你要面临的情况恐怕比这要糟糕上百倍啊!

所以这个所谓的“中等级别漏洞”,真的既不是中等,也不是漏洞。

再来看看第二个“漏洞”。

这一次要看看webpack-dev-server>chokidar>glob-parent依赖链。

在这条依赖链上,webpack-dev-server是一个仅用于开发的服务器,它可以在本地快速为应用程序提供服务。

chokidar被用来监视文件的更改。

glob-parent可以从文件系统监视模式中提取一部分文件系统路径。

这个报错显示,glob-parent上存在漏洞。如果一个攻击者提供了一个特制的文件路径,这会让运行变得非常非常慢……

桥豆麻袋!这不合理啊。

如果有人可以在你本地开发时入侵你的电脑,那么他最不会做的就是通过长文件路径来减慢你的开发速度了,他更想要的是窃取电脑中的信息啊!

所以,第二个“漏洞”也很荒谬。

第三个“漏洞”和第二个一样,只是换了个路径,同样不合理。

第四个“漏洞”可是高危型的啊,让我们来看看问题出在哪。

报错显示,css-what存在漏洞。

如果有人控制了你的电脑或者源代码,他就可以放置特殊的SVG文件,其中包含一个特殊的CSS选择器,这会让你的开发过程变得非常慢。

emmm……我实在不理解黑客在什么情况下会这么做。

除非可以使用SVG挖矿。

好吧,第四个“漏洞”依旧是没意义的。

最后一个“漏洞”也是如上这种情况,换汤不换药。

是CVE不够合理

如果这是发生在真实的开发过程中,看完npm audit这一通报错,很难有人血压不飙升……

但这还仅仅只是小哥举的一个栗子。

类似的假漏洞,实际上多达数百个。

它们这样捣乱,不仅浪费开发人员的时间和精力,甚至会导致一个项目的失败。

而且这对维护人员和初学者也非常不友好。

有人就表示,这是因为很多人都在提交正则表达式拒绝服务的漏洞报告。

这么多人在大量不同的项目中报告,无论如何这都很烦人,因为他们破坏了npm audit的机制。

修复所有可能的漏洞是好事,但是他们夸大了漏洞的严重程度。

有网友则认为:

这不是npm audit设计的问题,而是漏洞报告的问题。

有人补充,因为灰帽黑客想要获得更多的奖励,所以很多影响小甚至没影响的CVE报告激增。

激励机制导致现在一团糟。

甚至连SQLite的开发人员也曾在官网“吐槽”过CVE:

在大多情况下,这些错误并不是真正的漏洞,因为它本身并不会导致数据的丢失或危害。

对此,发帖小哥也提出了一些自己的建议和看法,希望能够让npm audit有所改进:

  • 在发布期间内联所有依赖项。例如Vite和Next.js都只是将它们的依赖项直接捆绑在包里,而不是依赖于npm的node_modules机制。从维护人员的角度来看,这样的启动时间更快、下载量更小,并且还不会有来自用户的假漏洞报告。不过内联机制可能有些违背npm的初衷。
  • 提供一些反诉漏洞报告的途径。有人就提议可以手动下架一些假漏洞报告,或者对一些假漏洞进行标记,提醒其他用户。

参考链接:
[1]https://overreacted.io/npm-audit-broken-by-design/
[2]https://news.ycombinator.com/item?id=27761334
[3]https://www.reddit.com/r/programming/comments/ofk77t/npm_audit_broken_by_design/
[4]https://www.sqlite.org/cves.html

版权所有,未经授权不得以任何形式转载及使用,违者必究。