GitHub 在 2026 年 11 月 2 日更新時程:從 12 月 2 日開始,所有公開儲存庫的 GitHub Actions 將預設封鎖 pull_request_target 事件,除非適用的 Actions event policy 明確允許。原定執行日是 11 月 2 日,現在多出一個月準備期;GitHub 另安排 11 月 9 日 16:00–18:00 UTC 與 11 月 16 日同時段的兩次 brownout,屆時受影響的 workflow 會建立失敗 run,但不會執行。
這項預設規則只影響公開儲存庫,GitHub 公告明確說明 private 與 internal repositories 不受影響,GitHub Enterprise Server 也不在本次範圍。它不是全面移除 pull_request_target:確有需要且完成安全檢查的團隊,仍可透過 policy 對特定 workflow 明確放行。真正需要避免的是為了消除失敗訊息,直接在整個組織層級無條件允許事件。
為什麼 pull_request_target 風險特別高
pull_request 對來自 fork 的程式碼採取低權限保護,通常提供唯讀 token 並保留 secrets;pull_request_target 則在 base repository 的受信任脈絡執行,可取得較高權限的 GITHUB_TOKEN 與 repository 或 organization secrets。它很適合標籤、分流與留言等需要對 base repository 寫入的工作,但不應拿來建置或執行 fork 提交的程式碼。
危險模式通常是 workflow 由預設分支載入,接著用 actions/checkout 指向 ${{ github.event.pull_request.head.sha }},再執行 npm install、測試、build script 或其他來自 PR 的檔案。攻擊者可以在 fork 修改 package scripts、Makefile 或設定,讓不受信任程式在持有 secrets 的 job 中執行。GitHub 文件把這類型態稱為 pwn request;即使 checkout 本身沒有執行程式,下一步的建置或安裝就可能完成攻擊鏈。
先找出會在 brownout 失敗的 workflow
先在 repository 與 organization 範圍搜尋 .github/workflows 中的 pull_request_target,再到 workflow execution protections 的 Insights 查看目前 evaluate mode 判定會被阻擋的 runs。兩種結果都要查:靜態搜尋能找出尚未觸發的檔案,Insights 則能反映實際套用的 policy 與執行情況。
為每支 workflow 記錄用途、觸發 activity、token permissions、使用的 secrets、是否 checkout PR head、是否執行或載入 PR 內容、runner 類型,以及是否寫入 issue、PR 或 release。不能只看 YAML 中有沒有明顯的 run;JavaScript action、套件安裝、讀取設定檔與下載 artifact 都可能間接執行不受信任內容。
11 月 9 日前先完成盤點,並把兩次 brownout 視為正式演練。失敗 run 應保留 error annotation 與 workflow 名稱,對照清單確認沒有漏掉依賴自動化。不要等 12 月 2 日才從大量紅燈反推哪些維護流程停擺。
三種遷移方案怎麼選
第一種是改成 pull_request。若工作只是 lint、test 或 build,而且不需要 secrets 或寫入 base repository,這通常是最直接的選擇。對 fork PR 使用受限 token,在隔離且短生命週期的 runner 執行;測試結果透過標準 check 呈現。這也能讓 workflow 檔案與被測程式碼來自同一個 PR merge context,較容易理解。
第二種是拆成低權限與高權限兩段。第一段用 pull_request 測試不受信任程式,只輸出最小、可驗證的結果;第二段在受信任事件中讀取結果並執行留言或標籤。artifact 必須視為不受信任資料,避免反序列化任意物件、覆寫路徑或直接執行內容。高權限段不應重新 checkout fork code,也要為 artifact 綁定 run、repository 與 commit 身分。
第三種才是保留 pull_request_target 並明確 allow。適用於只操作 metadata、確實需要 write token,且能證明不執行 PR 內容的 workflow。依 GitHub 安全指南,應把 GITHUB_TOKEN permissions 縮到最低、限制 secrets、使用隔離 runner,並檢查 cache poisoning。若必須設定 allow-unsafe-pr-checkout: true,名稱本身就是高風險警告;只有在檢出的內容永遠只當資料分析、不會被執行時才可能合理。
Policy 應精準到 workflow,而不是全面開洞
GitHub 公告建議透過 workflow file targeting 只允許確有需要的檔案。repository、organization 與 enterprise policies 可能分層套用,盤點時要確認最終有效規則,而不是只看單一 repository 設定。政策變更也應走 code review 或變更紀錄,寫明擁有者、原因與再次檢查日期。
驗收至少包含同 repository 分支 PR、外部 fork PR、Dependabot PR、第一次貢獻者、只有 metadata 變更,以及惡意測試案例。確認被允許的 workflow 完成預期操作、被禁止的 workflow 明確失敗、secrets 不出現在 fork job,且 token 無法執行非必要寫入。自架 runner 還要檢查網路可達範圍與工作區是否重用。
我的建議是預設改用 pull_request,需要特權操作時再拆分工作;只有 metadata automation 才考慮精準放行 pull_request_target。12 月 2 日是平台強制日期,但真正的第一個期限是 11 月 9 日 brownout。利用這兩次演練把 CI 權限邊界修正,比單純讓舊 workflow 繼續亮綠燈更重要。