以下の内容はhttps://sue445.hatenablog.com/entry/2026/02/18/121158より取得しました。


DependabotのSecurity Alertで作られたPRをいい感じにする

tl;dr;

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

モチベーション

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

今まではDependabot Security Alertが作ったPRに対して手でタイトルを修正をしてたのですが、自動化の機運が高まったのでやりました。

技術的なこと

dependabot/fetch-metadataalert-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 # to create security label
    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: |
    # Only prepend GHSA-ID or CVE-ID if the title does not already start with a GHSA or CVE prefix
    if [[ ! "${PR_TITLE}" =~ ^\[(GHSA|CVE)-[0-9A-Za-z-]+\] ]]; then
      # When multiple CVE identifiers exist for a GHSA advisory, we intentionally use a single CVE ID for the PR title prefix.
      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-tokenpermision-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 # PR branch is rebased

jobs:
  auto-merge:
    uses: sue445/workflows/.github/workflows/dependabot-security-alert.yml@main
    secrets:
      # TODO: Set secrets to Dependabot secrets
      app-id: ${{ secrets.GH_APP_ID }}
      private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
      # slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

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 # PR branch is rebased

jobs:
  dependabot-auto-merge:
    uses: sue445/workflows/.github/workflows/dependabot-auto-merge.yml@main
    secrets:
      # TODO: Set secrets to Dependabot secrets
      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: Set secrets to Dependabot secrets
      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-metadataalert-lookup でApp Tokenも使えることを追記するパッチを投げた

github.com

*1:追記にも書いたけどApp Tokenと一緒に使う例をパッチで投げました




以上の内容はhttps://sue445.hatenablog.com/entry/2026/02/18/121158より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14