tl;dr;
自分が管理してるOSSで Dependabot Security Alert で作られたPRに対して自動でタイトルにCVE IDをつけたりsecurityラベルをつけられるようにしました


モチベーション
PRのタイトルにCVE IDを書いておくとリリースノートでオートリンクされて便利です。

今まではDependabot Security Alertが作ったPRに対して手でタイトルを修正をしてたのですが、自動化の機運が高まったのでやりました。
技術的なこと
dependabot/fetch-metadata で alert-lookup: true をつければGHSA ID( https://github.com/advisories 上のID)がとれるので、GHSA IDからさらにCVE IDを取得してます。
あとラベルをつけておくと .github/release.yml でいい感じに分類できるようになるのでsecurityラベルをつけるようにしました。
workflow抜粋
- uses: actions/create-github-app-token@v2
id: app-token
with:
app-id: ${{ secrets.app-id }}
private-key: ${{ secrets.private-key }}
permission-contents: write
permission-issues: write
permission-pull-requests: write
permission-vulnerability-alerts: read
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: ${{ steps.app-token.outputs.token }}
alert-lookup: true
- name: Create `security` label if it doesn't exist
if: steps.metadata.outputs.ghsa-id != ''
run: |
if ! gh label list --json name --jq '.[].name' | grep -qx "security"; then
gh label create "security" --color "ffc107" --description "Security related issues or PRs"
echo "[INFO] Created security label"
fi
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Add security label and GHSA-ID (or CVE-ID if possible) to PR
if: steps.metadata.outputs.ghsa-id != ''
run: |
if [[ ! "${PR_TITLE}" =~ ^\[(GHSA|CVE)-[0-9A-Za-z-]+\] ]]; then
CVE_ID=$(gh api "/advisories/$GHSA_ID" --jq '.identifiers[] | select(.type=="CVE") | .value' 2>/dev/null || echo "")
if [ -n "${CVE_ID}" ]; then
PR_TITLE="[${CVE_ID}] ${PR_TITLE}"
else
PR_TITLE="[${GHSA_ID}] ${PR_TITLE}"
fi
fi
gh pr edit "$PR_URL" --title "${PR_TITLE}" --add-label "security"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
PR_TITLE: ${{ github.event.pull_request.title }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
GHSA_ID: ${{ steps.metadata.outputs.ghsa-id }}
細かいけど、 actions/create-github-app-token で permision-xxxx みたいな引数を明示的に渡すことで必要な権限をyaml上で宣言できて便利ですね。
workflow全文は https://github.com/sue445/workflows/blob/main/.github/workflows/dependabot-security-alert.yml を見てください。
注意点
Security advisoryの情報は secret.GITHUB_TOKENでは取得できません。
https://github.com/dependabot/fetch-metadata のREADMEには alert-lookup: true を使うにはPAT(Personal Access Token)を使えって書いてたけど調べたらGitHub AppでDependabot alertsのRead-onlyをつけることで取得できたのでPATを使うよりはこっちの方がセキュアかと思います。*1
あとGitHub Appを利用する場合にはGitHub Appの証明書をsecretにセットしてから利用することになると思いますが、Dependabotが参照できる必要があるのでAction Secretではなく Dependabot Secrets にセットする必要があります。


苦労したポイント
Dependabot security alertによるPR作成がworkflowのトリガになっているため、動作確認が非常に大変でした。(自分がメンテしてるOSSで使ってるライブラリで脆弱性が発生しないと動作確認ができない)
One more thing
privateリポジトリも含めると僕は100個以上のリポジトリをメンテしてるんですが、全てのリポジトリにさっきのような長大なworkflowファイルを置きたくなかったのでworkflow本体は https://github.com/sue445/workflows に置きつつ他のリポジトリからはそれをincludeする方式にしました。(最近のマイブーム)
各リポジトリでは下記のようなyamlを書くだけで使えるようにしてます。
name: dependabot-security-alert
on:
pull_request:
types:
- opened
- synchronize
jobs:
auto-merge:
uses: sue445/workflows/.github/workflows/dependabot-security-alert.yml@main
secrets:
TODO
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
https://github.com/sue445/workflows?tab=readme-ov-file#dependabot-security-alert
1つのworkflowファイルから複数の Reuse workflows をincludeすることができるので、実際には下記のように DependabotのPRをいい感じに自動マージするworkflow もセットで使っています。
name: dependabot-manager
on:
pull_request:
types:
- opened
- synchronize
jobs:
dependabot-auto-merge:
uses: sue445/workflows/.github/workflows/dependabot-auto-merge.yml@main
secrets:
TODO
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
dependabot-security-alert:
uses: sue445/workflows/.github/workflows/dependabot-security-alert.yml@main
secrets:
TODO
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
2026/2/20 23:50追記
https://github.com/dependabot/fetch-metadata の alert-lookup でApp Tokenも使えることを追記するパッチを投げた
github.com