yarn whyコマンドを駆使してGitHubセキュリティアラートに対応する

このエントリーをはてなブックマークに追加

yarn whyコマンドを駆使してGitHubセキュリティアラートに対応する

色々と教えてもらったので自分の備忘録としてブログにしておきます。

GitHubにはセキュリティアラートという機能があります。 この機能はリポジトリ内の依存ライブラリに脆弱性が発見された場合、アラートを投げてくれるというものです。 リポジトリの設定から機能を有効にしておくだけで、依存ライブラリの脆弱性を自動で検知してくれます。 JavaScriptの場合は定期的にリポジトリ内のpackage.jsonとlockファイルがチェックされれます。 packaeg.jsonやlockファイルの中のライブラリに脆弱性がないかを脆弱性データベースに問い合わせ、脆弱性が検知されたらアラートが発行されます。 ここで重要なことはpackage.jsonだけでなく、lockファイルも確認しているということです。 これはすなわちpackage.jsonに書かれている直接的な依存ライブラリに対して脆弱性を検知するだけでなく、lockファイルに書かれている、依存ライブラリが依存しているライブラリや、依存ライブラリが依存しているライブラリの依存しているライブラリなど、間接的に依存しているライブラリも脆弱性検知の対象になるということです。 さて、間接的に依存しているライブラリにセキュリティアラートが発行された場合どのように対応すれば良いのでしょうか。 本ブログでは間接的に依存しているライブラリにセキュリティアラートが発行された場合どのように対応すれば良いかを説明していきます。 (今回はyarnコマンドで説明します。npmコマンドでの解決方法は対象外です。)

セキュリティアラートの解決

セキュリティアラートの機能はがアラートが発行されたライブラリがどのライブラリの依存なのかを教えてくれません。 まずは、自身のpackage.jsonを確認してみて、リポジトリ内のコードが直接依存していないかを確認します。 直接依存している場合は簡単で、アラートが発行されたライブラリを脆弱性が解決されたバージョンに更新するだけです。 yarnではyarn upgreadeコマンドでパッケージのアップグレードが可能です。

yarn upgrade [package | package@tag | package@version | @scope/]... [--ignore-engines] [--pattern]

間接的に依存しているライブラリの更新

自身のpackage.jsonにアラートが発行されたライブラリがない場合、それは間接的に依存しているライブラリです。 この場合はまず、リポジトリ内で利用している、ライブラリのどれが依存しているかを確認する必要があります。 依存を確認するコマンドがyarn whyコマンドです。 yarn whyコマンドは以下の形式で実行します。

yarn why <query>

yarn whyコマンドを実行するとどのライブラリが依存しているかを確認することができます。

先日、自分の個人リポジトリでserialize-javascriptのライブラリに対してセキュリティアラートが発行されていました。

今回は例として、serialize-javescriptのセキュリティアラートを解決していきます。 (serialize-javescriptは直接依存しているライブラリではなく、間接的依存しているライブラリでした。)

まずはserialize-javascriptがどのライブラリに依存しているかを確認してみます。

yarn why serialize-javascript
yarn why v1.13.0
[1/4] 🤔  Why do we have the module "serialize-javascript"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "serialize-javascript@1.9.1"
info Reasons this module exists
   - "webpack#terser-webpack-plugin" depends on it
   - Hoisted from "webpack#terser-webpack-plugin#serialize-javascript"
info Disk size without dependencies: "24KB"
info Disk size with unique dependencies: "24KB"
info Disk size with transitive dependencies: "24KB"
info Number of shared dependencies: 0
✨  Done in 0.53s.

この出力結果を確認するとwebpackが依存しているterser-webpack-pluginがsirialize-javascriptに依存していることがわかります。

yarn why webpack
yarn why v1.13.0
[1/4] 🤔  Why do we have the module "webpack"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "webpack@4.41.1"
info Has been hoisted to "webpack"
info This module exists because it's specified in "devDependencies".
info Disk size without dependencies: "2.39MB"
info Disk size with unique dependencies: "9.14MB"
info Disk size with transitive dependencies: "28.24MB"
info Number of shared dependencies: 82
=> Found "next#webpack@4.39.0"
info This module exists because "next" depends on it.
info Disk size without dependencies: "2.5MB"
info Disk size with unique dependencies: "9.25MB"
info Disk size with transitive dependencies: "28.34MB"
info Number of shared dependencies: 82
✨  Done in 1.06s.

webpackに対してyarn whyを実行するとpackage.jsonのdevDependenciesに書かれているということがわかります。 ですので今回の場合はwebpackのversionを上げることでserialize-javascriptのversionの更新を行うことができます。 webpackのGitHubのversionページを眺めてみると以下のバージョンアップを確認しました。

セキュリティフィックスのためにterser-webpack-pluginのバージョンをあげたと書いてあります。 ですのでこの4.41.3のバージョンにアップグレードすればセキュリティアラートを解決することができます。 yarn upgradeコマンドでアップグレードします。

yarn upgrade webpack@4.41.3

package.jsonとlockファイルをpushすると見事セキュリティアラートが消えました!!

依存しているライブラリがセキュリティフィックスしていない場合

今回の例ではwebpackがしっかりとセキュリティフィックスを行っていました。 しかしながら、sirialize-javascriptがセキュリティフィックスされているけど、webpackはまだ対応できていないという場合があったりします。 その場合はwebpackをインストールする際に、無理やりserialize-javascriptをセキュリティフィックスしたバージョンでインストールするという設定が可能です。 yarnには選択的に依存関係を解決する方法があります。 package.json内にresolutionsというフィールドを追加し、その中にライブラリのバージョンを指定すると必ずそのバージョンでインストールされます。

今回の場合であれば、以下のように記述してもセキュリティアラートを解決することができます。 (serialize-javascriptは2.1.1で脆弱性を解決しました。)

{
  ・・・
  "dependencies": {
    ・・・
  },
  "resolutions": {
    "serialize-javascript": "2.1.1"
  }
}

このようにpackage.jsonに記述することで依存ライブラリの中でserialize-javascriptに依存している場合、serialize-javascriptは2.1.1で固定されてインストールされます。

まとめ

今回は間接的に依存しているライブラリに対してセキュリテイアラートが発行された場合にどのように解決すれば良いかを説明しました。 手順は以下のようになります。

GitHubのセキュリティアラートの機能ではCreate automated security updateという機能があり、Dependabotが直接アップグレードしてくれる方法もありますが、 この方法は間接的に依存しているライブラリでセキュリティアラートが発行された場合には利用できない可能性があります。 利用できない場合には今回紹介した方法を試してみてください。

以上です。