Skip to content

Dependabot を導入して脆弱性を直すまで ​

このページは、このサイト(study-lab)に Dependabot を導入し、見つかった脆弱性 4 件を修正するまでの記録です。作業は AI エージェントの Claude Code と一緒に進めました。

前半では Dependabot の仕組みと、自動では直せなかった脆弱性をどう直したかを解説します。後半では、AI と作業を進める中で起きた認識のずれと、その対処をまとめます。

用語の整理 ​

このページで使う主な用語です。

用語意味
依存パッケージ自分のプロジェクトが使っている、ほかの人が作った部品(ライブラリやツール)
脆弱性ソフトウェアのセキュリティ上の欠陥
PR(プルリクエスト)「このファイルをこう変更したい」という提案を GitHub 上に出す仕組み。承認されるまで本番には反映されない
マージPR で提案された変更を、main ブランチ(本番のコード)に取り込むこと
ビルドMarkdown などのソースから、公開用の HTML を生成する作業
CI(Continuous Integration)変更のたびに、自動でビルドやテストを行って確認する仕組み
デプロイビルドした結果を公開すること

Dependabot とは ​

Dependabot は、GitHub に組み込まれている機能です。依存パッケージを定期的に調べて、更新や脆弱性への対応を手伝ってくれます。無料で使えます。

Dependabot には、役割の違う 3 つの機能があります。

機能何をするか有効にする方法
Dependabot alerts依存パッケージに脆弱性が見つかったら、アラート(警告の通知)を出すリポジトリの設定
Dependabot security updates脆弱性を直したバージョンへ更新する PR を、自動で作るリポジトリの設定
Dependabot version updates脆弱性がなくても、新しいバージョンが出たら更新の PR を定期的に作る.github/dependabot.yml を置く

設定のしかた ​

1. version updates の設定ファイル ​

リポジトリに .github/dependabot.yml を置きます。このサイトでは、npm パッケージと GitHub Actions のアクションを、毎週月曜の 9 時(日本時間)に確認する設定にしました。

yaml
version: 2
updates:
  # npm パッケージ(package.json / package-lock.json)
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "09:00"
      timezone: "Asia/Tokyo"

  # GitHub Actions のアクション(.github/workflows/*.yml の uses:)
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "09:00"
      timezone: "Asia/Tokyo"
    # アクションの更新は 1 つの PR にまとめて届くようにする
    groups:
      github-actions:
        patterns:
          - "*"
  • package-ecosystem:何の部品を見張るかを指定します。npm は package.json の部品、github-actions はワークフロー内の uses: で指定したアクションです。
  • groups:複数の更新を 1 つの PR にまとめる設定です。アクションが 5 つあると、まとめないと PR が 5 つ届いてしまいます。

2. alerts と security updates の有効化 ​

リポジトリの Settings にあるセキュリティ関連の設定画面で、Dependabot alerts と Dependabot security updates を有効にします。

GitHub CLI(コマンドで GitHub を操作するツール gh)を使う場合は、次のコマンドで有効にできます。

bash
gh api -X PUT repos/OWNER/REPO/vulnerability-alerts
bash
gh api -X PUT repos/OWNER/REPO/automated-security-fixes

OWNER/REPO の部分は、自分のリポジトリ名に置き換えてください(例:hyodo-oumasa/study-lab)。

導入後に起きたこと ​

設定を push すると、Dependabot はすぐに最初の確認を始めました。数分のうちに、次のことが起きました。

  1. アクションの更新 PR が届いた 5 つのアクション(actions/checkout など)を新しいバージョンに上げる PR が 1 つ届きました。これで、デプロイのたびに出ていた「Node.js 20 は非推奨」という警告が解消されます。

  2. PR にチェックが付かなかった このときのワークフローは、main への push でしか動かない設定でした。そのため、PR の段階では「新しいアクションでもビルドできるか」を確かめる手段がありませんでした。そこで、PR のたびにビルドだけを試すワークフロー(pr-build.yml)を追加しました。そのうえで、PR に @dependabot recreate とコメントして PR を作り直してもらい、チェックを走らせました。

  3. 脆弱性のアラートが 4 件出た サイトを作る道具 VitePress が内部で使っている vite(開発サーバーを動かすツール)に 3 件、esbuild(プログラムを高速に変換するツール)に 1 件の脆弱性が見つかりました。どれも、手元で開発サーバーを動かしている間に、ほかの Web サイトから PC 内のファイルを読み取られるおそれがある、という種類のものでした。公開中のサイト(ただの HTML)には影響しません。

  4. 自動修正はできず、Actions に「失敗」が記録された security updates が修正の PR を作ろうとしましたが、作れませんでした。その記録が、GitHub の Actions 画面に「Dependabot Updates」という名前の失敗として残りました。サイトが壊れたわけではありません。脆弱性を自動では直せなかった、という意味です。

自動修正できなかった理由 ​

失敗した記録のログには、security_update_not_possible(セキュリティ更新は不可能)というエラーと、その理由が書かれていました。

text
"dependency-name": "vite",
"latest-resolvable-version": "5.4.21",
"lowest-non-vulnerable-version": "6.4.3",
"explanation": "vitepress@1.6.4 requires vite@^5.4.14"
項目値意味
lowest-non-vulnerable-version6.4.3脆弱性が直っている、いちばん低いバージョン
latest-resolvable-version5.4.21今の構成で上げられる上限
explanationvitepress@1.6.4 requires vite@^5.4.14VitePress が vite のバージョンを制限している

制限をかけていたのは誰か ​

この制限は、VitePress の開発チームがかけたものです。VitePress 自身の package.json に、次のように書かれています。

json
"vite": "^5.4.14"

先頭の ^(キャレット)は npm の記号で、「左端の数字(メジャーバージョン)は変えない範囲で、新しいものを使ってよい」という意味です。つまり「vite は 5.4.14 以上、6 未満」という指定になります。

0 から始まるバージョンの場合

esbuild のように 0.21.3 のような 0 始まりのバージョンでは、^0.21.3 は「0.21.3 以上、0.22 未満」という、より狭い範囲を意味します。esbuild は vite を経由してこの範囲に制限されていました。

メジャーバージョンが変わるときは、以前と互換性のない変更が入ることがあります。VitePress 1.6.4 の開発チームは vite 5 での動作しか保証していないため、このように制限していると考えられます。

Dependabot が制限を超えない理由 ​

Dependabot は、親の部品(ここでは VitePress)が指定した範囲の中でしかバージョンを上げません。親を新しい版に上げることで解決できないかも探しますが、新しい vite に対応した VitePress の安定版は、まだ出ていませんでした(2.0 は試験版のみ)。

親の指定を上書きするには、「保証のない組み合わせを使ってよいか」という人の判断が必要です。そのため、Dependabot はそこから先には進みません。これは故障ではなく、Dependabot の設計どおりの動作です。

人が選ぶ対応策 ​

自動修正できない脆弱性には、人が対応策を選びます。

対応策内容リスク
親の更新を待つVitePress の新しい安定版を待つ待つ間、脆弱性が残る
親を新しい版に上げるVitePress 2.0(試験版)に移行する試験版のため、動作が不安定になるおそれがある
overrides で強制する内部の部品のバージョンを、こちらから指定する親の開発チームが保証していない組み合わせになる
ツールを変える別のサイト生成ツールに乗り換える作業量が大きい
リスクを受け入れる理由を記録して、アラートを閉じる脆弱性が残る。影響が小さいと判断できる場合に限る

このサイトでは、overrides で強制する方法を選びました。変更が小さく、問題があればすぐに戻せるためです。

修正のしかた(overrides) ​

npm の overrides は、依存パッケージの内部で使われている部品のバージョンを、自分のプロジェクトの package.json から強制的に指定する機能です。

package.json に次の 3 行を追加しました。

json
"overrides": {
  "vite": "^6.4.3"
}

追加したら、npm install を実行して package-lock.json(実際にインストールするバージョンの記録)を更新します。vite を上げると、vite の内部で使われている esbuild も一緒に新しくなります。

部品変更前変更後
vite5.4.216.4.4
esbuild0.21.50.25.12

確認したこと ​

保証のない組み合わせになるので、反映する前に次のことを確認しました。

確認コマンド結果
脆弱性が残っていないかnpm audit0 件
サイトをビルドできるかnpm run docs:build成功
開発サーバーが動くかnpm run docs:dev各ページが表示された
公開されるページの内容が変わらないかビルド結果の文章を比較変化なし

この変更は PR として出し、PR のビルドチェックに合格したことを確認してからマージしました。マージ後、Dependabot のアラート 4 件は自動で「解決済み(fixed)」になりました。

上書きを外す時期 ​

overrides は一時的な対処です。VitePress が新しい vite に正式に対応した版を出したら、overrides を削除し、VitePress を上げる正規の方法に戻します。version updates が毎週確認しているので、新しい VitePress が出れば更新の PR が届きます。

最初の定期実行の結果と、cooldown ​

ここまでの内容は、設定を push した直後に起きたことです。その後、設定した曜日(月曜)になり、最初の定期実行が行われました。その記録を確認しました(2026 年 10 月 12 日)。

なお、この時点の設定ファイルには、Python の開発用パッケージ(pip)の確認も加えてあります(Python のコードに CI を付ける を参照)。

実行の記録 ​

定期実行は、GitHub の Actions の画面に、「Dependabot Updates」という名前で、見張る対象ごとに 1 件ずつ記録されます。

対象調べたもの結果
GitHub Actions のアクションactions/checkout など 6 つ成功。すべて最新で、更新は不要
npm のパッケージvitepress成功。最新で、更新は不要
Python の開発用パッケージpytest、ruff成功。更新は不要

3 件とも成功し、更新が必要なものはなかったので、PR は作られませんでした。更新がなければ、何も起きないのが、version updates の通常の動きです。

実行された時刻は、設定した 9 時ではなく、10 時 7 分から 10 時 9 分でした。公式ドキュメントには、time で実行の時刻を指定できるとありますが、指定した時刻ちょうどに実行されるかどうかは書かれていません。翌週の実行の時刻は、下の「2 回目の定期実行」に書いています。

「最新」が、使っているバージョンより古く表示された ​

実行の記録(ログ)の中に、想定と違う表示が 1 つありました。ruff は 0.17.0 を使っているのに、ログには次のように出ていました。

text
Checking if ruff 0.17.0 needs updating
Filtered out 1 versions due to cooldown
Latest version is 0.16.10
No update needed for ruff 0.17.0

「最新は 0.16.10」と、使っているものより古い番号が表示されています。理由は、2 行目にある cooldown です。

cooldown とは ​

cooldown は、公開されたばかりのバージョンを、一定の日数が経つまで、更新の候補にしない仕組みです。公式ドキュメント(Dependabot options reference)には、次のように書かれています。

項目内容
設定を書いていない場合既定で、3 日間の cooldown が適用される。新しいバージョンは、公開から 3 日が経つまで、更新の候補にならない
対象version updates だけ
対象外security updates には適用されない。既定の 3 日間も同じ
日数を変える方法dependabot.yml に cooldown を書き、default-days で日数を指定する
更新の大きさごとの指定semver-major-days、semver-minor-days、semver-patch-days で、大きな更新と小さな修正に、別々の日数を指定できる。npm と pip は対応している。GitHub Actions のアクションは、default-days だけ
対象の絞り込みinclude で適用するパッケージを、exclude で除外するパッケージを指定する。両方に当てはまる場合は、exclude が優先される

このサイトの設定ファイルには、cooldown を書いていません。そのため、既定の 3 日間が適用されています。アクションの確認のログにも、cooldown days 3 と表示されていました。

ruff 0.17.0 が公開されたのは 10 月 9 日で、定期実行は 10 月 12 日でした。公開から 3 日が経っていなかったので、Dependabot は 0.17.0 を候補から外し、その 1 つ前の 0.16.10 を「最新」と表示しました。すでに 0.17.0 を使っているので、「更新は不要」という判定は正しい結果です。

この仕組みから分かること ​

  • 新しいバージョンが公開されても、version updates の PR は、すぐには届かない。少なくとも 3 日が経ち、そのあとの定期実行で届く。週に 1 回の設定であれば、公開から届くまでに、最長で 10 日ほどかかることになる。
  • 脆弱性を直す更新(security updates)は、cooldown の対象ではないので、待たされない。
  • ログの「Latest version」は、cooldown で除外したあとの中での最新を指している。配布元での最新とは、一致しないことがある。

公開された直後のバージョンは、不具合が見つかって取り下げられることがあります。数日待ってから取り込む動きは、そうしたバージョンを避けるのに役立ちます。これは一般的な考え方で、公式ドキュメントの cooldown の説明には、理由までは書かれていません。

2 回目の定期実行と、最初の更新の PR ​

翌週の月曜日(2026 年 10 月 19 日)にも、定期実行の記録を確認しました。

実行された時刻 ​

回実行された時刻(日本時間)設定した 9 時からの遅れ
1 回目(10 月 12 日)10 時 7 分〜10 時 9 分約 1 時間 7 分
2 回目(10 月 19 日)9 時 15 分〜9 時 16 分約 15 分

どちらも、9 時より前には動かず、少し遅れて動きました。遅れ方は、回によって違いました。決まった時刻ちょうどに動くものではなく、「指定した時刻を過ぎてから、しばらくのうちに動く」と考えておくのがよさそうです。時刻に厳密さを求める用途には、向いていません。

更新の PR が、はじめて作られた ​

2 回目の定期実行では、Dependabot が、はじめて version updates の PR を作りました。

項目内容
PRBump ruff from 0.17.0 to 0.17.1
中身Python の書き方を検査する道具(ruff)を、0.17.0 から 0.17.1 に上げる。requirements-dev.txt の 1 行だけが変わる
作られた時刻10 月 19 日 9 時 21 分(定期実行の約 5 分後)
チェックPR 用のビルドと、Python の CI(3 つの OS × 2 つの版のテスト)が、すべて合格した

1 回目の定期実行では、ruff 0.17.0 が、公開から 3 日経っていないので、cooldown で候補から外されていました。その次の版の 0.17.1 は、10 月 16 日(日本時間)に公開され、2 回目の定期実行の時点で、3 日が経っていました。cooldown の期間を過ぎたので、更新の候補になり、PR が作られたことになります。

この PR は、内容を確かめてマージしました。手元の仮想環境(venv)にも、同じ版を入れ直して、検査が通ることを確かめています。

ここまでで、version updates の一連の流れを、実際に確かめられました。

  1. 決まった曜日に、定期実行が動く
  2. 新しい版があっても、公開から 3 日経つまでは、候補にしない
  3. 候補になったら、更新の PR を作る
  4. PR のチェックが自動で動き、合格すれば、人が確かめてマージする

AI と進める中で起きた認識のずれと、その対処 ​

この作業は Claude Code と一緒に進めましたが、AI の説明と、こちらの理解の間にずれが生じ、解決までに時間がかかりました。起きたずれと、その対処をまとめます。

起きたずれ影響対処
AI が「自動では直せない」を「直せない」と受け取り、脆弱性を残す方向で話を進めた解決が遅れた「見つけて、直すまで」を目的に置き直し、直し方を調べ直させた。その結果、overrides で直せると分かった
AI が「失敗」の意味(脆弱性を自動では直せなかったこと)を説明しないまま、失敗の表示を止める案(security updates の無効化)を勧め、同意を求めた。実質的には、脆弱性の放置につながる案への同意を求めていた判断に必要な情報がないまま、脆弱性を放置するかどうかを決めさせられそうになった「失敗」と言われたら、何が失敗したのか、それによって何が残るのかを AI に説明させる。表示や通知を止める案が出たら、止めた結果、何を見逃すことになるのかを確認する
AI が用語を説明せずに承認を求めた理解が追いつかないまま承認が進んだ承認の前に、何をするのか・何が起きるのか・リスクは何か・どう戻すのか、の 4 点を AI に説明させる
想定内の結果を、AI が未知の問題のように報告した。同じ結果を「失敗」とも「成功」とも言った混乱して、確認のやり取りが増えた想定される結果は事前に伝えさせる。評価は「何を目的にして、何を期待していたか」を基準に述べさせる

AI に説明を求めるときのルール ​

上の対処をまとめたものです。AI エージェントへの指示文として、そのまま使える形にしています。

text
- 用語や略語は、初めて出てくるところで意味を説明してください。
- 承認を求める前に、次の 4 点を示してください。
  1. 何をするのか
  2. その結果、何が起きるのか(想定される副作用も含めて)
  3. リスクは何か
  4. 問題があったとき、どう戻すのか
- 結論だけを先に言わず、何をしようとして、何が起きたのかを順に説明してください。
- 想定できる結果は、実行する前に伝えてください。結果を報告するときは、想定内か想定外かを最初に区別してください。
- 「成功」「失敗」と評価するときは、目的と期待していた結果を示してから述べてください。こちらの言葉に合わせて評価を変えないでください。
- ツールが「自動では直せない」と言っても、それを「直せない」と同じ意味に扱わず、ほかの解決策を調べてください。
- リスクを受け入れるかどうかは、あなたが決めずに、選択肢と根拠を示してこちらに判断させてください。
- 通知や表示を止める案を出すときは、止めた結果、何を見逃すことになるのかを説明してください。

まとめ ​

  • Dependabot には、脆弱性を知らせる alerts、自動で直す security updates、定期的に更新を提案する version updates の 3 つの機能がある。
  • 間接的に使っている部品が、親の部品のバージョン指定(^)で古い範囲に縛られている場合、Dependabot は自動では直せない。Actions に記録される「失敗」は、そのことを意味する。
  • 自動で直せない脆弱性は、人が対応策を選んで直す。overrides は有効な手段だが、保証のない組み合わせになるので、確認と、上書きを外す計画をセットにする。
  • PR 用のビルドチェックは、Dependabot より先に用意しておくとよい。更新の PR が届いた時点で、自動で確認できる。
  • 関連する PR をマージする順番に注意する。このサイトでは、アクションの更新 PR を脆弱性の修正 PR より先にマージしたため、その間に Dependabot の失敗の記録が 2 件増えた。
  • version updates には、設定を書かなくても、3 日間の cooldown が適用される。公開されたばかりのバージョンは、3 日が経つまで更新の候補にならない。security updates には適用されない。
  • 定期実行は、設定した時刻ちょうどではなく、少し遅れて動く。遅れ方は、回によって違った(約 15 分〜約 1 時間)。
  • AI と作業するときは、理解できるまで説明を求める。承認は、内容を理解してから行う。