GitHub Actions 9 月更新:vulnerability-alerts 與 reusable workflow 怎麼用?
GitHub 在 2026 年 9 月初公布的 Actions 更新,對日常維護最有感的不是多了一個版本號,而是 workflow 權限與 reusable workflow 的身分資訊變得更明確。這次公告同時包含 self-hosted runner deprecation API;Runner 版本盤點已整理在 GitHub Actions 自架 Runner 更新清單,本文集中處理另外兩個會直接影響 YAML 與稽核流程的變化。
直接答案是:需要讀取 Dependabot alerts 的 job,在最小範圍加入 vulnerability-alerts: read;需要知道 reusable workflow 實際由哪個 repository、ref 和 commit 執行時,在被呼叫的 workflow 內讀取 job.workflow_ref、job.workflow_sha、job.workflow_repository 與 job.workflow_file_path。這兩項功能都不等於取得 secret scanning 權限,也不能繞過 GHES 或 fork/Dependabot 執行環境的限制。
先把 9 月更新分成三種問題
| 更新 | 主要用途 | 你要改的地方 |
|---|---|---|
vulnerability-alerts permission | 讓 GITHUB_TOKEN 讀取 Dependabot alerts | workflow 或特定 job 的 permissions |
job.workflow_* context | 在 job 中辨識目前 workflow 檔案的來源 | reusable workflow 的步驟與稽核輸出 |
| self-hosted runner deprecation API | 盤點版本何時停止註冊或執行 | 既有 runner inventory 與維運腳本 |
不要把三項更新塞進同一個「安全性升級」步驟。前兩項是 workflow 內容與權限設計;第三項是 runner 生命週期。拆開後,失敗時比較容易判斷是 token 權限、context 不可用,還是 runner 版本問題。
用 vulnerability-alerts: read 讀 Dependabot alerts
GitHub Actions 的 permissions 可以設定在 workflow 頂層,也可以設定在單一 job。若只讓一個稽核 job 呼叫 Dependabot alerts,建議把權限放在 job 層級,讓其他 job 不會一起拿到不需要的 token scope。未明確指定的權限會變成 none;vulnerability-alerts 只接受 read 或 none,不能設定 write。
下面的例子只列出目前 repository 的 Dependabot alerts,不需要 checkout 原始碼,因此沒有額外加入 contents 權限:
name: List Dependabot alerts
on: workflow_dispatch:
jobs: list-alerts: runs-on: ubuntu-latest permissions: vulnerability-alerts: read steps: - name: Read Dependabot alerts env: GH_TOKEN: ${{ github.token }} GH_REPO: ${{ github.repository }} run: | gh api --paginate "/repos/${GH_REPO}/dependabot/alerts?per_page=100" \ --jq '.[] | [.number, .state, .dependency.package.name, .security_advisory.severity] | @tsv'這段 YAML 的重點不是 gh api 本身,而是權限邊界:
- 只會授予這個 job 讀取 Dependabot alerts 的權限,其他未列出的 scope 維持
none。 - 如果 job 同時需要 checkout,才另外加入
contents: read;不要因為常見範本而把contents: write一起打開。 - Secret scanning 不是這個 permission 的延伸功能。GitHub 文件指出,secret scanning 需要 GitHub App 或 personal access token 的相應能力,不能只靠
vulnerability-alerts: read取代。 - fork pull request 與 Dependabot 觸發的 workflow 仍有 token 只讀、不可使用 secrets 等限制;測試 permission 時要用實際事件再驗證一次。
若既有 workflow 已經在 job 層級明確設定 permissions,加入新的 key 後也要重新檢查其他 scope。GitHub 的行為是未列出的權限設為 none,所以「只補一行」可能讓原本依賴 contents 或 pull-requests 的步驟失敗。
用 job.workflow_* 確認 reusable workflow 來源
Reusable workflow 最常見的稽核問題是:呼叫端寫的是一個 ref,但實際執行 job 的 workflow 檔案來自哪個 repository、哪個 commit?新的 job context 欄位讓被呼叫的 workflow 可以把來源記錄下來:
| Context | 代表的資訊 |
|---|---|
job.workflow_ref | 定義目前 job 的 workflow 檔案 ref |
job.workflow_sha | 定義目前 job 的 workflow 檔案 commit SHA |
job.workflow_repository | 定義目前 job 的 workflow 檔案 repository |
job.workflow_file_path | workflow 檔案在該 repository 的路徑 |
在 reusable workflow 內,這組值用來辨識 reusable workflow 自己的來源;它不是把 caller 的 repository 當成被呼叫檔案的來源。這個差異對跨 repository 的部署範本、稽核 log 和 checkout 很重要。
例如,平台團隊可以在 reusable workflow 內 checkout 定義該 workflow 的 repository 與 commit,並只記錄不含 secret 的來源欄位:
name: Reusable deploy
on: workflow_call: inputs: environment: required: true type: string
jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout workflow source uses: actions/checkout@v6 with: repository: ${{ job.workflow_repository }} ref: ${{ job.workflow_sha }}
- name: Record workflow source env: WORKFLOW_REF: ${{ job.workflow_ref }} WORKFLOW_SHA: ${{ job.workflow_sha }} WORKFLOW_REPOSITORY: ${{ job.workflow_repository }} WORKFLOW_FILE: ${{ job.workflow_file_path }} run: | printf 'workflow_ref=%s\n' "$WORKFLOW_REF" printf 'workflow_sha=%s\n' "$WORKFLOW_SHA" printf 'workflow_repository=%s\n' "$WORKFLOW_REPOSITORY" printf 'workflow_file_path=%s\n' "$WORKFLOW_FILE"這些欄位是來源資訊,不是授權決策的替代品。若部署流程要求只能使用已審核的 reusable workflow,仍應在 caller 端 pin 到受控的 commit SHA,並維持最小 token 權限;不要只把 workflow_ref 印進 log 就當作供應鏈驗證完成。若 reusable workflow 還會傳遞 secrets,權限和傳遞方式可對照 GitHub Actions reusable workflow 的 secrets 邊界。
GHES 與跨事件測試不能省略
GitHub 官方 contexts 文件目前註明,這四個 job.workflow_* 欄位在 GitHub Enterprise Server(GHES)不提供。若同一份 workflow 同時支援 GitHub.com 與 GHES,應把這些欄位視為可選資料,或由 caller 透過明確 input 傳入需要的識別資訊;不要在沒有 fallback 的情況下直接讓 null 進入部署路徑。
建議用以下矩陣做一次驗證:
| 測試情境 | 要確認的結果 |
|---|---|
| 手動執行 Dependabot audit job | API 可讀取 alerts,未列出的 token scope 沒有被意外打開 |
| caller 呼叫跨 repository reusable workflow | job.workflow_repository 與 job.workflow_sha 指向被呼叫的 workflow 來源 |
| fork pull request 或 Dependabot 事件 | 只讀 token 與 secrets 限制仍符合預期,log 不會洩漏敏感值 |
| GHES runner | job.workflow_* 不可用時,fallback 或明確跳過,不讓部署誤判來源 |
| 權限縮減後的完整 workflow | checkout、artifact、pull request comment 等既有步驟仍各自擁有必要的 read scope |
測試時要保存 workflow run、事件類型、repository 與 commit,而不只是貼上一段成功的 console output。權限問題通常只在特定 trigger 或 fork 權限模式下出現。
一個可回滾的採用順序
- 先複製現有 workflow 的成功 run 與目前
permissions設定,作為 baseline。 - 只在 Dependabot audit job 加入
vulnerability-alerts: read,先驗證 API 和其他步驟。 - 在 reusable workflow 加入
job.workflow_*的非敏感 log,確認 caller、ref、SHA 和 path 的實際值。 - 對 GitHub.com、fork/Dependabot 事件與 GHES 分別測試;為不可用的 context 加 fallback。
- 最後才把來源資訊接到稽核或部署策略,並保留能回到舊版 workflow 的 commit。
這樣可以把「取得資料」和「相信資料」分成兩個 review。新 context 能幫你看清楚 job 由哪個 workflow 檔案定義,但真正的供應鏈安全仍取決於 ref pinning、token 權限、runner 和部署端的驗證。
實務上,這次更新的重點是兩個小而清楚的邊界:Dependabot alerts 用 vulnerability-alerts: read 精準授權;reusable workflow 用 job.workflow_* 記錄執行來源。先在單一 job 和非敏感 log 驗證,再擴大到部署或稽核流程,回滾與定位都會比較容易。
常見問題
Q: vulnerability-alerts 可以設定成 write 嗎?
A: 不行。GitHub Actions workflow syntax 目前只接受 read 或 none;它是讀取 Dependabot alerts 的唯讀權限。若工作需要修改其他安全資料,應依該 API 的授權模型另行設定,不能把這個 key 當成通用安全權限。
Q: 加上 vulnerability-alerts: read 就能讀 secret scanning 結果嗎?
A: 不能。Dependabot alerts 與 secret scanning 是不同的資料與授權邊界;secret scanning 需要 GitHub App 或 personal access token 的相應能力。不要用 workflow 的 GITHUB_TOKEN permission 直接推論另一個安全 API 也能呼叫。
Q: job.workflow_* 在 GHES 也能直接使用嗎?
A: 不能直接假設可以。官方 contexts 文件目前將這四個欄位列為 GHES 不提供;跨平台 workflow 應準備可選欄位、明確 input 或跳過該段稽核邏輯的 fallback。
參考資料:
GitHub Changelog:2026 年 9 月初 Actions 更新
回報錯字、失效連結,或告訴我你想看的延伸主題。