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 時(日本時間)に確認する設定にしました。
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)を使う場合は、次のコマンドで有効にできます。
gh api -X PUT repos/OWNER/REPO/vulnerability-alertsgh api -X PUT repos/OWNER/REPO/automated-security-fixesOWNER/REPO の部分は、自分のリポジトリ名に置き換えてください(例:hyodo-oumasa/study-lab)。
導入後に起きたこと
設定を push すると、Dependabot はすぐに最初の確認を始めました。数分のうちに、次のことが起きました。
アクションの更新 PR が届いた 5 つのアクション(
actions/checkoutなど)を新しいバージョンに上げる PR が 1 つ届きました。これで、デプロイのたびに出ていた「Node.js 20 は非推奨」という警告が解消されます。PR にチェックが付かなかった このときのワークフローは、
mainへの push でしか動かない設定でした。そのため、PR の段階では「新しいアクションでもビルドできるか」を確かめる手段がありませんでした。そこで、PR のたびにビルドだけを試すワークフロー(pr-build.yml)を追加しました。そのうえで、PR に@dependabot recreateとコメントして PR を作り直してもらい、チェックを走らせました。脆弱性のアラートが 4 件出た サイトを作る道具 VitePress が内部で使っている vite(開発サーバーを動かすツール)に 3 件、esbuild(プログラムを高速に変換するツール)に 1 件の脆弱性が見つかりました。どれも、手元で開発サーバーを動かしている間に、ほかの Web サイトから PC 内のファイルを読み取られるおそれがある、という種類のものでした。公開中のサイト(ただの HTML)には影響しません。
自動修正はできず、Actions に「失敗」が記録された security updates が修正の PR を作ろうとしましたが、作れませんでした。その記録が、GitHub の Actions 画面に「Dependabot Updates」という名前の失敗として残りました。サイトが壊れたわけではありません。脆弱性を自動では直せなかった、という意味です。
自動修正できなかった理由
失敗した記録のログには、security_update_not_possible(セキュリティ更新は不可能)というエラーと、その理由が書かれていました。
"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-version | 6.4.3 | 脆弱性が直っている、いちばん低いバージョン |
latest-resolvable-version | 5.4.21 | 今の構成で上げられる上限 |
explanation | vitepress@1.6.4 requires vite@^5.4.14 | VitePress が vite のバージョンを制限している |
制限をかけていたのは誰か
この制限は、VitePress の開発チームがかけたものです。VitePress 自身の package.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 行を追加しました。
"overrides": {
"vite": "^6.4.3"
}追加したら、npm install を実行して package-lock.json(実際にインストールするバージョンの記録)を更新します。vite を上げると、vite の内部で使われている esbuild も一緒に新しくなります。
| 部品 | 変更前 | 変更後 |
|---|---|---|
| vite | 5.4.21 | 6.4.4 |
| esbuild | 0.21.5 | 0.25.12 |
確認したこと
保証のない組み合わせになるので、反映する前に次のことを確認しました。
| 確認 | コマンド | 結果 |
|---|---|---|
| 脆弱性が残っていないか | npm audit | 0 件 |
| サイトをビルドできるか | 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 を使っているのに、ログには次のように出ていました。
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 を作りました。
| 項目 | 内容 |
|---|---|
| PR | Bump 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 の一連の流れを、実際に確かめられました。
- 決まった曜日に、定期実行が動く
- 新しい版があっても、公開から 3 日経つまでは、候補にしない
- 候補になったら、更新の PR を作る
- PR のチェックが自動で動き、合格すれば、人が確かめてマージする
AI と進める中で起きた認識のずれと、その対処
この作業は Claude Code と一緒に進めましたが、AI の説明と、こちらの理解の間にずれが生じ、解決までに時間がかかりました。起きたずれと、その対処をまとめます。
| 起きたずれ | 影響 | 対処 |
|---|---|---|
| AI が「自動では直せない」を「直せない」と受け取り、脆弱性を残す方向で話を進めた | 解決が遅れた | 「見つけて、直すまで」を目的に置き直し、直し方を調べ直させた。その結果、overrides で直せると分かった |
| AI が「失敗」の意味(脆弱性を自動では直せなかったこと)を説明しないまま、失敗の表示を止める案(security updates の無効化)を勧め、同意を求めた。実質的には、脆弱性の放置につながる案への同意を求めていた | 判断に必要な情報がないまま、脆弱性を放置するかどうかを決めさせられそうになった | 「失敗」と言われたら、何が失敗したのか、それによって何が残るのかを AI に説明させる。表示や通知を止める案が出たら、止めた結果、何を見逃すことになるのかを確認する |
| AI が用語を説明せずに承認を求めた | 理解が追いつかないまま承認が進んだ | 承認の前に、何をするのか・何が起きるのか・リスクは何か・どう戻すのか、の 4 点を AI に説明させる |
| 想定内の結果を、AI が未知の問題のように報告した。同じ結果を「失敗」とも「成功」とも言った | 混乱して、確認のやり取りが増えた | 想定される結果は事前に伝えさせる。評価は「何を目的にして、何を期待していたか」を基準に述べさせる |
AI に説明を求めるときのルール
上の対処をまとめたものです。AI エージェントへの指示文として、そのまま使える形にしています。
- 用語や略語は、初めて出てくるところで意味を説明してください。
- 承認を求める前に、次の 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 と作業するときは、理解できるまで説明を求める。承認は、内容を理解してから行う。