GitHub Actions 安全性審查,針對工作流程中的漏洞進行利用分析。當被要求「審查 GitHub Actions」、「稽核工作流程」、「檢查 CI 安全性」、「GHA 安全性」、「工作流程安全性審查」,或審查 .github/workflows/ 中的 pwn 請求、表達式注入、憑證竊取及供應鏈攻擊時使用。專注於利用,並提供具體的 PoC 情境。
<!--
攻擊模式與真實案例來源:StepSecurity (2025) 的 HackerBot Claw 活動分析
https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation
-->
GitHub Actions 安全性審查
找出 GitHub Actions 工作流程中可被利用的漏洞。每個發現必須包含具體的利用情境——如果你無法建構攻擊,就不要回報。
此技能編碼了真實 GitHub Actions 漏洞的攻擊模式——而非泛泛的 CI/CD 理論。
範圍
審查提供的工作流程(檔案、差異或儲存庫)。視需要研究程式碼庫,以在回報前追蹤完整的攻擊路徑。
需審查的檔案
.github/workflows/*.yml— 所有工作流程定義action.yml/action.yaml— 儲存庫中的複合動作.github/actions/*/action.yml— 本機可重複使用動作- 工作流程載入的設定檔:
CLAUDE.md、AGENTS.md、Makefile、.github/下的 shell 腳本
不納入範圍
- 其他儲存庫中的工作流程(僅註明依賴關係)
- GitHub App 安裝權限(若相關則註明)
威脅模型
僅回報外部攻擊者可利用的漏洞——即沒有儲存庫寫入權限的人。攻擊者可以從 fork 開啟 PR、建立 issue 和發表評論。他們不能推送到分支、觸發 workflow_dispatch 或觸發手動工作流程。
不要標記需要寫入權限才能利用的漏洞:
workflow_dispatch輸入注入——需要寫入權限才能觸發- 受保護分支上僅
push工作流程中的表達式注入 workflow_call輸入注入,且所有呼叫者均為內部- 僅
workflow_dispatch/schedule工作流程中的機密
信心水準
僅回報高和中信心水準的發現。不要回報理論性問題。
| 信心水準 | 標準 | 行動 |
|---|---|---|
| 高 | 追蹤完整攻擊路徑,確認可被利用 | 回報並附上利用情境與修復方式 |
| 中 | 攻擊路徑部分確認,但連結不確定 | 回報為需要驗證 |
| 低 | 理論性或已在其他地方緩解 | 不回報 |
對於每個高信心發現,提供全部五個要素:
- 進入點 — 攻擊者如何進入?(fork PR、issue 評論、分支名稱等)
- 酬載 — 攻擊者發送了什麼?(實際程式碼/YAML/輸入)
- 執行機制 — 酬載如何執行?(表達式展開、checkout + 腳本等)
- 影響 — 攻擊者獲得了什麼?(權杖竊取、程式碼執行、儲存庫寫入權限)
- PoC 草稿 — 攻擊者會遵循的具體步驟
如果你無法建構全部五項,則回報為中信心(需要驗證)。
步驟 1:分類觸發器並載入參考資料
對於每個工作流程,識別觸發器並載入適當的參考資料:
| 觸發器 / 模式 | 載入參考資料 |
|---|---|
pull_request_target |
references/pwn-request.md |
issue_comment 搭配命令解析 |
references/comment-triggered-commands.md |
run: 區塊中的 ${{ }} |
references/expression-injection.md |
| PAT / 部署金鑰 / 提升的憑證 | references/credential-escalation.md |
| Checkout PR 程式碼 + 設定檔載入 | references/ai-prompt-injection-via-ci.md |
| 第三方動作(尤其是未固定版本) | references/supply-chain.md |
permissions: 區塊或機密使用 |
references/permissions-and-secrets.md |
| 自託管執行器、快取/成品使用 | references/runner-infrastructure.md |
| 任何已確認的發現 | references/real-world-attacks.md |
選擇性載入參考資料——僅載入與找到的觸發器相關的內容。
步驟 2:檢查漏洞類別
檢查 1:Pwn 請求
工作流程是否使用 pull_request_target 並且 checkout fork 的程式碼?
- 尋找
actions/checkout且ref:指向 PR head - 尋找會來自 fork 的本機動作(
./.github/actions/) - 檢查是否有任何
run:步驟執行來自 checkout 的 PR 程式碼
檢查 2:表達式注入
在外部可觸發的工作流程中,run: 區塊內是否使用了 ${{ }} 表達式?
- 找出每個
run:步驟中的每個${{ }}表達式 - 確認該值是由攻擊者控制的(PR 標題、分支名稱、評論內容——而非數字 ID、SHA 或儲存庫名稱)
- 確認表達式位於
run:區塊中,而非if:、with:或工作層級的env:
檢查 3:未經授權的命令執行
由 issue_comment 觸發的工作流程是否在未經授權的情況下執行命令?
- 是否有
author_association檢查? - 任何 GitHub 使用者都能觸發該命令嗎?
- 命令處理器是否也使用了可注入的表達式?
檢查 4:憑證提升
提升的憑證(PAT、部署金鑰)是否可被不受信任的程式碼存取?
- 每個機密的爆炸半徑為何?
- 受損的工作流程能否竊取長期有效的權杖?
檢查 5:設定檔投毒
工作流程是否從 PR 提供的檔案載入設定?
- AI 代理指令:
CLAUDE.md、AGENTS.md、.cursorrules - 建置設定:
Makefile、shell 腳本
檢查 6:供應鏈
第三方動作是否安全地固定版本?
檢查 7:權限與機密
工作流程權限是否最小化?機密是否適當限定範圍?
檢查 8:執行器基礎設施
自託管執行器、快取或成品是否安全使用?
安全模式(不要標記)
在回報前,檢查該模式是否實際安全:
| 模式 | 為何安全 |
|---|---|
pull_request_target 沒有 checkout fork 程式碼 |
從不執行攻擊者程式碼 |
run: 中的 ${{ github.event.pull_request.number }} |
僅數字——不可注入 |
${{ github.repository }} / github.repository_owner |
儲存庫擁有者控制此項 |
${{ secrets.* }} |
非表達式注入向量 |
if: 條件中的 ${{ }} |
由 Actions 執行階段評估,而非 shell |
with: 輸入中的 ${{ }} |
作為字串參數傳遞,非 shell 評估 |
| 固定到完整 SHA 的動作 | 不可變參考 |
pull_request 觸發器(非 _target) |
在 fork 環境中執行,使用唯讀權杖 |
受保護分支上 workflow_dispatch/schedule/push 中的任何表達式 |
需要寫入權限——超出威脅模型 |
關鍵區別: ${{ }} 在 run: 區塊中危險(shell 展開),但在工作/步驟層級的 if:、with: 和 env: 中安全(Actions 執行階段評估)。
步驟 3:回報前驗證
在納入任何發現之前,請閱讀實際的工作流程 YAML 並追蹤完整的攻擊路徑:
- 閱讀完整工作流程 — 不要僅依賴 grep 輸出
- 追蹤觸發器 — 確認事件並檢查控制執行的
if:條件 - 追蹤表達式/checkout — 確認它在
run:區塊中或實際引用 fork 程式碼 - 確認攻擊者控制 — 驗證該值對應於外部攻擊者可以設定的內容
- 檢查現有緩解措施 — 環境變數包裝、author_association 檢查、受限權限、SHA 固定
如果任何環節中斷,標記為中信心(需要驗證)或放棄該發現。
如果所有檢查都沒有產生發現,請回報零發現。不要憑空捏造問題。
步驟 4:回報發現
## GitHub Actions 安全性審查
### 發現
#### [GHA-001] [標題] (嚴重性:嚴重/高/中)
- **工作流程**:`.github/workflows/release.yml:15`
- **觸發器**:`pull_request_target`
- **信心水準**:高——透過攻擊路徑追蹤確認
- **利用情境**:
1. [逐步攻擊]
- **影響**:[攻擊者獲得的成果]
- **修復方式**:[修復問題的程式碼]
### 需要驗證
[中信心項目,附上需要驗證的說明]
### 已審查且安全
[已審查並確認安全的工作流程]
如果沒有發現:「未識別出可被利用的漏洞。所有工作流程已審查且安全。」






