脆弱性のある依存パッケージをnpm auditで監査する

[フューチャーAdventCalendar2020](https://qiita.com/advent-calendar/2020/future) 15日目です。

昨日は、iwamoto-san(@qiiwa)さんによる、[PingでLinuxサーバの死活監視をするべきではないという話](https://qiita.com/qiiwa/items/29d086c87f3e4b98839b)でした。

# はじめに

こんにちは。2019年4月入社の市川です。
現在私はVue.jsでのSPA（Single Page Application）の開発業務に携わらせていただくことが多いのですが、プロジェクトで使用しているパッケージの脆弱性対応を業務で行いました。

今回は私が調べながら脆弱性対応を行った内容を、こちらで紹介をしていきたいと思います。

# 環境
- npm 6.14.8
- node 14.9.0

# 現状把握

npm v.6.0.0より、そのプロジェクトで使用しているパッケージの依存関係を監査して脆弱性が存在するかどうかを確認できる、`npm audit` コマンドが用意されています。(https://docs.npmjs.com/cli/v6/commands/npm-audit)

まず今回はこちらを使用して自分のプロジェクトで使用しているパッケージの依存関係にどの程度の脆弱性があるのかを確認してみましょう。

実行すると、下記のような出力結果を得ることができます。

```zsh
$ npm audit

                       === npm audit security report ===                        
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ foo                                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ bar                                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ hoge                                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/fuga                            │
└───────────────┴──────────────────────────────────────────────────────────────┘
...
...
...（割愛）
...
found 100 vulnerabilities (95 low, 5 high) in 200 scanned packages ・・・①
  run `npm audit fix` to fix 98 of them. ・・・②
  2 vulnerabilities require manual review. See the full report for details.　・・・③
```

（↑脆弱性件数の数値を少しいじってます）

npm auditによって下記のようなことがわかりました。

① プロジェクトで使用している200個のpackageのうち100件の脆弱性があり、
　 そのうち95件はlow level、5件はhigh levelであること
② 100件のうち98件の脆弱性に関しては`npm audit fix` コマンドで脆弱性対応ができること
③ 2つの脆弱性については手動での確認が必要なこと

# npm audit fix での脆弱性対応

現状も把握できたので、脆弱性対応を実施していきます。
上記の出力結果にある `npm audit fix` コマンドはnpmのv6.1.0から使用でき、node_modulesに存在する大抵の脆弱性を自動修正してくれます。

では、`npm audit fix` を実行しましょう。

```sh
$ npm audit fix

+ hoge@1.17.30
added 1 package from 1 contributor, removed 10 packages and updated 15 packages in 10.000s

63 packages are looking for funding
  run `npm fund` for details

fixed 98 of 100 vulnerabilities in 200 scanned packages
  2 vulnerabilities required manual review and could not be updated
```

`npm audit fix` により、100個の脆弱性のうち98個に対応することができました。便利ですね。
ログに出力されている通り、パッケージの依存関係によって `npm audit fix` で自動で修正しきれない脆弱性が残ってしまうことがあり、こちらは手動で解消しなくてはいけません。

今回、手動で対応しなければならない脆弱性が2つ残っているのでその内容を確認します。

```sh

$ npm audit
                       === npm audit security report ===                        
                                                                                
# Run  npm update webpack --depth 2  to resolve 2 vulnerabilities
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Remote Code Execution                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ serialize-javascript                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ @vue/cli-plugin-babel [dev]                                  │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ @vue/cli-plugin-babel > webpack > terser-webpack-plugin >    │
│               │ serialize-javascript                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/1548                            │
└───────────────┴──────────────────────────────────────────────────────────────┘

┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Remote Code Execution                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ serialize-javascript                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ @vue/cli-plugin-eslint [dev]                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ @vue/cli-plugin-eslint > webpack > terser-webpack-plugin >   │
│               │ serialize-javascript                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/1548                            │
└───────────────┴──────────────────────────────────────────────────────────────┘
```

npm auditを実行すると、上記のような出力結果を得ました。
ログに出力されている、`More info` のリンクにアクセスすると詳細な内容が記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/1d32cf53-cb3d-01f8-65b8-40f644cfbd8c.png)
(https://www.npmjs.com/advisories/1548)

この2つの脆弱性に対応するためには、`npm update webpack --depth 2` を実行してwebpackをupdateするよう記載があるので、それに従って `npm update webpack --depth 2` を実行し、npm auditで出力結果を確認します。

```
$ npm update webpack --depth 2
...
...
$ npm audit                                                                     
                       === npm audit security report ===                        
                                                                                
found 0 vulnerabilities in 200 scanned packages
```

こちらで依存しているパッケージの脆弱性が0件となることが確認できました。

# 脆弱性対応を自動化する

ソフトウェアの世界では、日々脆弱性が発見されては修正されてを繰り返しています。
人間が常に脆弱性の情報をキャッチアップし、アップデート作業を行うのは少し億劫ですよね

プライベートで使用しているGithubでは脆弱性が発見された時、自動で脆弱性対応を行うPull Requestを作成する設定を行っているのですが、業務の方ではあまり自動化できていないので、 gitlab-ciをなどを活用した脆弱性対応が行えないか後日検証してみたいと思います。


## 参考

- [npm-audit | npm Docs](https://docs.npmjs.com/cli/v6/commands/npm-audit)
- [Auditing package dependencies for security vulnerabilities | npm Docs](https://docs.npmjs.com/auditing-package-dependencies-for-security-vulnerabilities#check-for-mitigating-factors)