如何高效地升级npm依赖包至安全版本?

2,629 阅读2分钟

如果网上被爆出某某依赖包有漏洞,我们该如何高效安全的升级依赖包版本?安全问题不容小觑,下面做一个实践小结。

一、npm audit的基本原理

在npm@6版本中,增加了一个新命令npm audit,该命令会在项目中下载新的依赖包或者更新依赖包之后自动运行,如果你在项目中使用了具有已知安全问题的依赖,就收到官方的警告通知。

image.png

执行 npm audit fix命令可以帮助我们自动修复漏洞,它底层执行的命令其实是 npm update。

1、npm update如何知道每个模块的最新版本?

原因是npm提供了一个叫做registry的服务,以 npmjs.org 为例,它的查询服务地址是:registry.npmjs.org/

后面跟上模块名,就会返回这个模块的所有版本信息。

比如:registry.npmjs.org/lodash

image.png

2、如何查看所有依赖包的安全漏洞?

1)执行 npm audit

可以大概浏览所有依赖包的安全漏洞情况。

看下图,它会展示漏洞等级、包名、依赖的路径、包的深度、修复策略

image.png

2)npm audit --json 查看更详细的漏洞详情

我们看下lodash的漏洞详情:
action:修复策略(有update、install、install major、review这几种操作)
serverity:漏洞等级
found_by:发现该漏洞的用户
vulnerable_versions:受影响的版本
patched_versions:已修复的版本

image.png

3、npm update更新npm包的版本机制是怎样的?

在X.Y.Z结构的版本号中,分为以下几种模式:

1)^
从左向右,遇到第一个非零数字是不可修改的,下一个数字可以更改。
例如 :^2.3.5,第一个非零数字是2,2不可修改。表示的版本号是>=2.3.5 && <3.0.0
例如:^0.1.2,第一个非零数字是1,1不允许修改,表示版本号>=0.1.2 && < 0.2.0

  1. ~
    匹配大于X.Y.Z的更新Z的版本号
    比如 ~1.2.3表示版本号>=1.2.3 && < 1.3.0

3)x:
可以替代X、Y、Z中任意一个,表示该位置可更新
1.2.x 表示 >=1.2.0 && < 1.3.0
1.x 表示>=1.0.0 && < 2.0.0

  1. *
    表示任意版本都可以

npm update会在semver版本的范围内更新到最新的兼容版本。

二、版本修复策略

1、直接依赖漏洞


安装完依赖包后,如果有收到 run npm audit fix的告警,需要输入npm audit fix命令自动修复非安全版本依赖包。
需要注意的是,npm update 只会检测更新最顶层的依赖,更新更深层次的依赖版本,需要使用 --dept h 指定更新的深度。


2、间接依赖漏洞

假设我们现在依赖的路径很深,比如element的依赖包里面依赖了lodash@^3.0.0(>=3.0.0&&<4.0.0),4.17.12不在这个范围之内,
我们直接通过升级lodash版本已经行不通,这时只能向上一层依赖看,如果element这时有个新版本已经更新了lodash的依赖,且版本
范围在4.17.12内,那么就可以直接通过命令 npm update element --depth=2来更新。(npm update 只会检测更新最顶层的依赖)

3、强制修复漏洞

按照上面的例子,如果新版本的element里面依赖的lodash也不在安全版本范围内,这时npm update element --depth=2也不管用了。
这时我们可以执行npm audit fix --force来强制执行安装最新的依赖项,他会忽略当前指定的semver范围,强制更新到最新版本,所以一定要慎用,
如果非要升级,一定要保证兼容之前的版本使用。