脆弱性の警告を受けたnpmパッケージの依存関係を力技で直す

## 概要
2018年4月に[npm v6.0.0がリリースされ](https://blog.npmjs.org/post/173260195980/announcing-npm6)、セキュリティチェックができるコマンド[`npm audit`](https://docs.npmjs.com/cli/audit)が追加されました。
さらに2018年5月には[npm6.1.0がリリースされ](https://blog.npmjs.org/post/174001864165/v610-next0)、セキュリティチェックに追加して脆弱性のある箇所を自動修正してくれるサブコマンド[`npm audit fix`](https://docs.npmjs.com/cli/audit)が追加されました。
この機能は非常に便利で、node_modulesに存在する大抵の脆弱性を自動修正してくれます。しかし、パッケージの依存関係によって自動で直しきれない脆弱性が残ってしまうことがあり、現時点ではこれを手動で解消しなくてはいけません。その方法を共有します。

## 実践
### まずは$npm audit
まずは任意のプロジェクトで`npm audit`をポチッと実行します。

```terminal:terminal
$ npm audit

//中略。ここに脆弱性のあるパッケージ一覧が表示されます

found 25 vulnerabilities (5 low, 19 moderate, 1 high) in 26755 scanned packages
  25 vulnerabilities require manual review. See the full report for details.
```
<img width="827" alt="スクリーンショット 2018-06-18 15.17.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/119598/867fa9e9-f6d5-31fa-32a7-440644cc3b99.png">
すると、「25個の脆弱性があって、そのうち1個がレベル**high**ですよ。上の詳細一覧を見てね」と教えてくれます。
で上の方にスクロールして一覧を見ると

```terminal
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ minimatch                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=3.0.2                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ gulp-order                                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ gulp-order > minimatch                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/118                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
```
パッケージgulp-orderの中で使われているパッケージminimatchにレベル**high**の脆弱性が発見されました。開発が止まってしまったパッケージでは往々にしてこうしたセキュリティホールが放置されています。
脆弱性の内容は正規表現を使ったDoS攻撃（[ReDoS](https://blog.ohgaki.net/regex-dos-redos)）を食らう危険があるとのこと。
しかしその脆弱性はminimatch v3.0.2以降でパッチ修正されているということなので、修正適用を試みます。


### 修正済みパッケージをインストール
問題のあるパッケージがわかったところで、修正済みパッケージ（今回はminimatchの最新版）をインストールします。

```terminal
$ npm i minimatch -D
+ minimatch@3.0.4
updated 1 package and audited 26756 packages in 12.79s
```
無事に現時点での最新版であるminimatch v3.0.4がインストールされました。

### ローカルフォルダ内の問題ファイルを確認
今度はFinderから（ターミナルの方が慣れている人はターミナルで）フォルダを開きパッケージgulp-orderの中で使われているパッケージminimatchを探します。

![スクリーンショット 2018-06-18 15.48.57.png](https://qiita-image-store.s3.amazonaws.com/0/119598/725ecf79-c74d-af0b-f1ce-a91b81eedcb4.png)

ありました。

#### $npm lsで確認

```terminal
$ npm ls minimatch
```
と[`ls`](https://docs.npmjs.com/cli/ls)コマンドを打つと、プロジェクト内で使われているminimatchの依存関係と使用されているバージョンを見ることができます。
![スクリーンショット 2018-06-19 9.48.40.png](https://qiita-image-store.s3.amazonaws.com/0/119598/a8c5b99f-911f-398d-d396-764e71a55e94.png)
重複排除されたminimatchは`deduped`と表記され、一番下のminimatchだけが生きていることを示しています。`deduped`なパッケージはnode_modulesの中から削除してOK。またバージョン違いでもパッケージの後方互換性が確認できればdedupedでないパッケージも削除してOKです。

### 削除
gulp-orderの中で古いバージョンのminimatchが使われ、また後方互換性のあるパッケージがnode_modulesの中にインストールされていることがわかったので、無慈悲に削除します。
![スクリーンショット 2018-06-18 16.02.58.png](https://qiita-image-store.s3.amazonaws.com/0/119598/63619c3a-e83c-b6cc-e6ab-2f1786db4132.png)
（ポイー）
### $npm dedupe
最後に`$npm dedupe`コマンドで依存関係整理を実行。

```terminal
$ npm dedupe
audited 26759 packages in 8.811s
found 24 vulnerabilities (5 low, 19 moderate)
  run `npm audit fix` to fix them, or `npm audit` for details
```
<img width="828" alt="スクリーンショット 2018-06-18 16.23.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/119598/9d6741dd-ab84-ed8a-5e31-0c806220e1bd.png">
お！レベル**high**の脆弱性がなくなってる〜。

というわけで、脆弱性のあるnpmパッケージの依存関係を力技で修正することができました。

いずれこんなことしなくて良くなりそうですが。ってかもうなってるのを私が知らないだけかも…。

<ins>
## 追記 - ERR! 400 Bad Requestで`npm audit`に失敗する時
下記を参照。
- [ERR! 400 Bad Requestでnpm auditに失敗した時の対処法](https://qiita.com/hibikikudo/items/5db676a4de8ea498d66d)

## 追記 - 力技じゃない直し方
### package.jsonのアップデートを自動化する
- [自動でnpmライブラリをアプデ&プルリクしてくれるサービスのgreenkeeperがすごく便利だった](https://qiita.com/itkrt2y/items/c0e77a4e3cda173917bb)
- [Automated Dependency Updates with Renovate](https://www.slideshare.net/teppeis/automated-dependency-updates-with-renovate-102769685)

[greenkeeper](https://greenkeeper.io/)と[Renovate](https://renovatebot.com/)はどちらもpackage.jsonのアップデートを自動化してくれる便利ツールです。
私はweb制作テンプレートの管理にRenovateの無料プランを利用していますがなかなか快適です。
とはいえパッケージがメジャーアップデートする時には破壊的な変更を含む（gulpfile.jsなどのビルドプロセスを書き換える必要が生じる）場合があるので、そこはご注意ください。
</ins>
<ins>
### パッケージの開発者にプルリクを送る、またはissue機能でお願いする
パッケージの開発者またはメンテナがGithubでアクティブに活動している場合に限りますが、開発者に修正のプルリクを送るかissue機能でお願いするのも一つの方法です。
このやりとりは大抵の場合英語になりますが、英語への苦手意識を取り去ってトライしてみましょう！
issueの立て方はこちらを参照→[Managing your work on GitHub / Creating an issue](https://help.github.com/articles/creating-an-issue/)
もし対応してもらえた場合にはメッセージや絵文字👍🎉で感謝を表すといいと思います。</ins>