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


概要

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

実践

まずは$npm audit

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

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.


すると、「25個の脆弱性があって、そのうち1個がレベルhighですよ。上の詳細一覧を見てね」と教えてくれます。
で上の方にスクロールして一覧を見ると

┌───────────────┬──────────────────────────────────────────────────────────────┐
│ 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)を食らう危険があるとのこと。
しかしその脆弱性はminimatch v3.0.2以降でパッチ修正されているということなので、修正適用を試みます。

修正済みパッケージをインストール

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

$ npm i minimatch -D
+ [email protected]
updated 1 package and audited 26756 packages in 12.79s

無事に現時点での最新版であるminimatch v3.0.4がインストールされました。

ローカルフォルダ内の問題ファイルを確認

今度はFinderから(ターミナルの方が慣れている人はターミナルで)フォルダを開きパッケージgulp-orderの中で使われているパッケージminimatchを探します。

ありました。

$npm lsで確認

$ npm ls minimatch

lsコマンドを打つと、プロジェクト内で使われているminimatchの依存関係と使用されているバージョンを見ることができます。

重複排除されたminimatchはdedupedと表記され、一番下のminimatchだけが生きていることを示しています。dedupedなパッケージはnode_modulesの中から削除してOK。またバージョン違いでもパッケージの後方互換性が確認できればdedupedでないパッケージも削除してOKです。

削除

gulp-orderの中で古いバージョンのminimatchが使われ、また後方互換性のあるパッケージがnode_modulesの中にインストールされていることがわかったので、無慈悲に削除します。

(ポイー)

$npm dedupe

最後に$npm dedupeコマンドで依存関係整理を実行。

$ 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


お!レベルhighの脆弱性がなくなってる〜。

というわけで、脆弱性のあるnpmパッケージの依存関係を力技で修正することができました。
いずれこんなことしなくて良くなりそうですが。ってかもうなってるのを私が知らないだけかも…。

追記 - ERR! 400 Bad Requestでnpm auditに失敗する時

下記を参照。
- ERR! 400 Bad Requestでnpm auditに失敗した時の対処法

追記 - 力技じゃない直し方

package.jsonのアップデートを自動化する

greenkeeperRenovateはどちらもpackage.jsonのアップデートを自動化してくれる便利ツールです。
私はweb制作テンプレートの管理にRenovateの無料プランを利用していますがなかなか快適です。
とはいえパッケージがメジャーアップデートする時には破壊的な変更を含む(gulpfile.jsなどのビルドプロセスを書き換える必要が生じる)場合があるので、そこはご注意ください。

パッケージの開発者にプルリクを送る、またはissue機能でお願いする

パッケージの開発者またはメンテナがGithubでアクティブに活動している場合に限りますが、開発者に修正のプルリクを送るかissue機能でお願いするのも一つの方法です。
このやりとりは大抵の場合英語になりますが、英語への苦手意識を取り去ってトライしてみましょう!
issueの立て方はこちらを参照→Managing your work on GitHub / Creating an issue
もし対応してもらえた場合にはメッセージや絵文字👍🎉で感謝を表すといいと思います。