本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
前言
接上篇文章 如何有效利用ESLint处理前端Sonar Issues问题,公司部署的sonar扫描平台里,还集成了Dependency-check扫描,即会扫描代码里第三方引用是否有漏洞。
这种扫描工具很多,笔者项目用到的是 OWASP dependency-check,另外推荐一个漏洞扫描网站:security.snyk.io/
对前端来讲,第三方引用基本就两种形式,一个是直接在html引用js\css等静态资源;二是npm package。
第一种不说了,一般升级到最新就行。本文主要说npm package问题,看了下几个项目,扫出来的问题,都不是顶层依赖top-level dependencies的问题,而是其下面的子依赖sub dependencies的version有漏洞问题。
举个例子
比如下图有个项目,引用了copy-webpack-plugin eslint等,然后dependency-check扫描出来有个依赖某个版本有漏洞,即 glob-parent@5.1.2。(这里是假设,5.1.2应该没漏洞,这里可以查到)
然后运行下npm ls glob-parent,发现是copy-webpack-plugin下面的fast-glob@3.2.12里引用了glob-parent@5.1.2,然后6.0.2是没问题的,所以现在目标要把glob-parent升级到6.0.2。
此例里顶层依赖就是指copy-webpack-plugin eslint这些;子依赖就是指 fast-glob glob-parent这些。
升级顶层依赖top-level dependencies
首先想到的方法,一般是直接升级顶层依赖top-level dependencies到最新version,这样其下面的子依赖sub dependencies的version也就会跟着升级,达到目的。
这里推荐一个工具:npm-check-updates,可以快速查看dependencies的当前和最新版本都是多少,还可以一键升级。
但是有些时候新version包可能会影响功能,到了项目后期应该可能会更大;而且有时候即使升级到最新version,其下面的子依赖version可能还是旧的(有漏洞的)。
所以这个只能当做首要方案,如果达不到预期,就得想有没有其它备用方案可以解决。下面介绍下几种方案。
方案1:直接install有问题的dependency
比如上面例子,直接 install glob-parent -D,即把glob-parent引用提升为顶层依赖,但实际效果是:
没起到效果,子依赖里依然是旧version。但是这种方式我隐约记得之前解决什么问题来着是好用的,这块还得研究下npm dependency的引用关系。此方案可以当做一个不太可行的备用方案,不好用再看下面。
方案2:npm-force-resolutions
一个可以强制 npm 安装特定的传递依赖版本的插件,不需要install新包,可以直接配置运行。
首先在package.json中添加resolutions,并定义好你想要修复的dependency以及期望version:
"resolutions": {
"glob-parent": "6.0.2"
}
然后在scripts中添加preinstall,以便在每次运行npm install之前对package-lock.json文件进行修复:
"scripts": {
"preinstall": "npx npm-force-resolutions"
},
然后再运行下npm install(不用删package-lock.json),会自动先执行preinstall,此时再执行npm ls glob-parent,就会发现对应version...还是没变。
这个方案笔者在之前项目里用过,是可行的。最近项目更多用的是方案3,可能是不支持npm v8了,作者已经两年没更新了。对于低版本的npm,可以考虑尝试此方案。
另外,虽然npm ls的version没变,package-lock.json里的version已经变了,这样有可能会通过Dependency-check扫描,可以试试。但是注意这个操作对package-lock.json改动很大,注意不要影响打包或者功能。
方案3:overrides
npm v8+ 版本新引入的一个功能,可以对npm dependency依赖包version进行重写。
用法很简单,只需要在package.json里加个overrides配置:
"overrides": {
"glob-parent": "6.0.2"
}
然后再运行下npm install(不用删package-lock.json),此时再执行npm ls glob-parent,就会发现对应version就变了。而且package-lock.json里也只更换了version,没有其它多余改动。
这样就可以满足需求了,这应该算是官方出的npm-force-resolutions替代方案,这也可能是作者不更新了的原因吧。
还支持对不同父依赖下的子依赖设置不同的version,详情用法参考官方文档:docs.npmjs.com/cli/v8/conf…
总结
整理下解决步骤:
- 升级顶层依赖
top-level dependenciesversion 到最新或指定版本。 - 如果npm version<8.0,使用
npm-force-resolutions; - 如果npm version>=8.0,使用
overrides。