Dependabotで依存関係の脆弱性を検出して自動修正するPRを作る手順

公開日:
目次

npm audit を眺めては「あとで対応しよう」と放置し、気づいたら脆弱性アラートが二桁になっていた、という状態をしばらく続けていました。手で npm update を打って差分を確認して、テストを回して、PRを出して、というのを脆弱性ごとにやるのが面倒で後回しになる。これを止めたくてDependabotを設定したら、検出から修正PRの作成まで勝手に回るようになったので、その導入手順を残しておきます。

脆弱性まわりの alerts と security updates を分けて理解する

ここを混同していると設定でつまずきます。Dependabotのこの領域は、役割の違う2つの機能に分かれています。

  • Dependabot alerts: 依存しているライブラリに既知の脆弱性が出たときに「これが危ない」と通知する検出側
  • Dependabot security updates: そのアラートに対して、修正版へ上げるPRを自動で開く修正側

GitHubの公式ドキュメントはこの2つをはっきり書き分けています。

Dependabot security updates are automated pull requests that help you update dependencies with known vulnerabilities.[1]

検出するだけのalertsと、検出を受けてPRまで作るsecurity updatesは別物だ、という前提で読み進めてください。alertsだけ有効にしても通知が溜まるだけで、PRは作られません。security updatesまで入れて初めて「検出から修正PR作成まで」が自動で回ります。

有効化の前提と手順

security updatesを使うには先に2つを有効にしておく必要があります。dependency graph(依存関係グラフ)と、Dependabot alertsです。

The Dependabot security updates feature is available for repositories where you have enabled the dependency graph and Dependabot alerts.[1:1]

順番としては、リポジトリの Settings から進みます。

  1. SettingsAdvanced Security(リポジトリによっては Code security 表記)を開く
  2. Dependency graph を有効にする
  3. Dependabot alerts を有効にする
  4. Dependabot security updates を有効にする

publicリポジトリではdependency graphとalertsはデフォルトで有効になっていることが多いので、その場合はsecurity updatesのトグルを入れるだけで済みます。privateリポジトリだと下の2つから順に有効にする必要があります。

ここで一つ押さえておきたいのは、security updatesは dependabot.yml が無くても動くということです。トグルを入れた時点で、修正版が存在するアラートに対してDependabotが勝手にPRを開き始めます。「設定ファイルを書かないと何も起きない」と思って身構えていると、ここで拍子抜けします。最短で脆弱性対応を回したいだけなら、トグルを入れて終わりでも構いません。

dependabot.yml は何のために書くのか

では dependabot.yml は何をするためのものか。これは主に version updates(脆弱性に関係なく、依存を最新に追従させる定期更新)を設定するファイルです。security updatesはトグルだけで動きますが、version updatesはこのファイルを置かないと動きません。

.github/dependabot.yml に置く最小構成はこれだけです。

.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "daily"
  • package-ecosystem: パッケージマネージャの種類。npm、pipbundlergithub-actions など、使っているエコシステムを指定する
  • directory: マニフェスト(package.json など)があるディレクトリ。ルート直下なら /
  • schedule.interval: チェック頻度。daily / weekly / monthly などを指定する

schedule.interval が取れる値は daily weekly monthly のほか、quarterly semiannually yearly cron も使えます(公式オプションリファレンス準拠)。

複数のエコシステムを使っているなら、updates の配下にエントリを並べます。GitHub Actionsのワークフローも追従させたい、というのはよくあるので一緒に書いておきます。

.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

注意したいのは、このファイルの設定の一部はsecurity updatesのPRにも効くという点です。公式リファレンスでは、各オプションに「Security updates」を示すシールドチェックのアイコンが付いていて、そのアイコンが付いたオプションはsecurity updatesのPR作成にも反映されると書かれています(target-branch を使う場合を除く)。[2]

ただし全部が両方に効くわけではなく、open-pull-requests-limit(同時に開けるPR数の上限、デフォルト5)のようにversion updates専用のオプションもあります。security updatesのPRを dependabot.yml で細かく制御したい場合は、そのオプションがsecurity updatesにも効くのかをリファレンスのアイコンで確認してから書くのが安全です。

自動修正PRが来たあと

PRが自動で開いても、マージは手動です。ここは自動化されません。脆弱性修正のPRには、対象のCVE・どのバージョンへ上げるか・互換性スコアが添えられて来るので、それを見てCIが通っているのを確認してからマージします。マージするとひも付いていたアラートは自動でクローズされます。

逆に言うと、CIが通らないとここで詰まります。テストが薄いリポジトリだと「上がってきたPRが本当に安全か」を人間が判断する負荷が残るので、Dependabotを入れる前提としてテストとCIをある程度整えておくと、PRを信頼してさっさとマージできるようになります。自分の場合、ここのCIが緑かどうかだけ見てマージする運用に落ち着いていて、依存の脆弱性対応にかけていた時間がほぼ消えました。

放置していたアラートが二桁あったのが、トグルを入れた翌日にはPRが束で飛んできて、それを順にマージしていったら片付いた、というのが導入直後の体験でした。検出から修正までを自分の手で繋いでいた部分を、まるごと外に出せた感覚です。手で npm audit fix を打ち続けている人は、まずsecurity updatesのトグルだけ入れてみるといいと思います。

脚注
  1. About Dependabot security updates - GitHub Docs ↩︎ ↩︎

  2. Dependabot options reference - GitHub Docs ↩︎