三个字:供应链管理。除了在我们的例子中,“供应”是依赖或“第三方库”。
这不是 npm 独有的问题。这是软件开发中的普遍问题。这相当于在谷歌上搜索“螺丝”制造商,然后使用您看到的第一个“螺丝”制造商,不要询问“螺丝”的规格,然后使用这些“螺丝”并希望他们能做到工作正确,不会断裂,腐蚀/生锈太快,并且可以承受压力......无需检查这些螺丝是否经过测试,是否有适当的质量控制。我们可以这样做,因为如果您的软件有缺陷或易受攻击,通常不会有人死亡。如果一个结构因为螺丝有问题而倒塌......那是另一回事。那里有责任。软件中没有这样的责任......除非你' 如果您的控制软件有错误,则在发生软件错误或巨大而昂贵的机器损坏(和/或危及生命)时实际上危及生命的一些行业重新工作。我的意思是死得很严重。如果您必须能够支持实时通信以实时控制某些进程,并且如果您使用的第三方库产生CPU故障,因为它有问题......因为那样你的机器就会真正损坏。
软件开发的问题是我们“谷歌”搜索“一些库”提供“一些功能”,然后我们只是“npm install”、“go get”、“pip install”它,我们很高兴。那里没有验证过程。你怎么知道这个包提供了它声称的东西?你知道它的测试效果如何吗?你知道它是否还在积极维护吗?你知道什么是 API 稳定性保证吗?你可以“去获取”一些包,一周后包就完全坏掉了,因为即使是“官方”的 go 代码也可能没有任何 API 稳定性保证。
您使用什么版本约束?foo >= 1.5
. 如果foo >= 1.6
引入后门怎么办?使用最新版本编译您的代码的人将在其中包含此后门。如果您使用foo == 1.5
但有不同的镜像并且您的同事用于构建您的软件的镜像包含该软件包的恶意版本怎么办?并且不要忘记:如果您安装/使用包/库?您不仅需要验证该包/库...您还需要验证整个依赖关系树。
我们需要的是一个认证过程。一旦公司/开发人员认为他们的包准备好了,他们就会发布它,然后独立的代码审查和安全公司审查包,一旦有合理程度的信心认为这个包是“安全”的,他们就会签署它。然后,您只能使用已签名的依赖项,并且除了使用foo == ("1.5", "abc734defef373f..")
.
您如何将其应用于 npm?
不要在没有审查的情况下安装 npm 包。作者是谁?一般的代码质量如何?最后一次更新是什么时候?最近的几次提交是什么?它的安装有什么作用?它有适当的测试吗?代码/测试覆盖率是多少?有多少人在使用它?谁在使用它?
软件开发的重点是提供更新、新事物、更新、新事物。适当的测试和适当的“第三方代码管理”成本很高,而且大多数情况下公司和消费者都不愿意支付这个价格。毕竟,这始终是“风险与成本”。如果安全漏洞的代价是某些用户窃取了他们的凭据......没人在乎。他们不能起诉你。在最坏的情况下,这会让你在“公众形象”方面付出一些代价。如果最糟糕的是一个对某些用户不起作用的有缺陷的软件......你可以承受一些使用免费版本的用户的愤怒......如果有像“保修”这样的东西,这可能会改变
在您的网站上使用第三方 javascript 也存在此问题。一样。无论您使用什么语言、框架、技术,问题几乎完全相同:如果您想要安全……您需要验证第三方代码。
另一件事:
有些包/库只提供很少的实用程序......你可以在 3 小时内自己编写的东西......也许一天。如果您不关心更多的依赖项(并且更多的依赖项会使您的依赖项管理复杂化),这不是问题,但是如果您这样做......有时实际上不使用这些简单的库并自己编写功能会更省力,这样你可以完全控制它并且可以正确地测试它。经验法则是,如果您验证别人的代码所花费的时间比您自己编写代码所花费的时间长……那么您自己编写。如果您只需要整个框架中的一个或两个函数,这也适用。它'
除此之外:......您可以在安装过程中阻止到非白名单网站的流量,这意味着这种特定的攻击将不起作用,但不适用于仅删除随机文件或插入后门的恶意安装脚本现有文件或其他任何东西。您必须仔细阅读安装脚本。