gha-security-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<!--
Attack patterns and real-world examples sourced from the HackerBot Claw campaign analysis
by StepSecurity (2025): https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation
-->
<!--
攻击模式和真实案例来自StepSecurity 2025年发布的HackerBot Claw活动分析:https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation
-->
GitHub Actions Security Review
GitHub Actions安全审查
Find exploitable vulnerabilities in GitHub Actions workflows. Every finding MUST include a concrete exploitation scenario — if you can't build the attack, don't report it.
This skill encodes attack patterns from real GitHub Actions exploits — not generic CI/CD theory.
查找GitHub Actions工作流中的可利用漏洞。每一项发现都必须包含具体的利用场景——如果你无法构建攻击路径,就不要上报该问题。
本技能收录了来自真实GitHub Actions漏洞利用的攻击模式,而非通用的CI/CD理论知识。
Scope
审查范围
Review the workflows provided (file, diff, or repo). Research the codebase as needed to trace complete attack paths before reporting.
审查提供的工作流(文件、diff或仓库)。上报前需根据需要研究代码库,追踪完整的攻击路径。
Files to Review
需审查的文件
- — all workflow definitions
.github/workflows/*.yml - /
action.yml— composite actions in the repoaction.yaml - — local reusable actions
.github/actions/*/action.yml - Config files loaded by workflows: ,
CLAUDE.md,AGENTS.md, shell scripts underMakefile.github/
- — 所有工作流定义文件
.github/workflows/*.yml - /
action.yml— 仓库内的复合actionaction.yaml - — 本地可复用action
.github/actions/*/action.yml - 工作流加载的配置文件:、
CLAUDE.md、AGENTS.md、Makefile目录下的shell脚本.github/
Out of Scope
超出范围的内容
- Workflows in other repositories (only note the dependency)
- GitHub App installation permissions (note if relevant)
- 其他仓库中的工作流(仅需注明依赖关系即可)
- GitHub App安装权限(若相关可注明)
Threat Model
威胁模型
Only report vulnerabilities exploitable by an external attacker — someone without write access to the repository. The attacker can open PRs from forks, create issues, and post comments. They cannot push to branches, trigger , or trigger manual workflows.
workflow_dispatchDo not flag vulnerabilities that require write access to exploit:
- input injection — requires write access to trigger
workflow_dispatch - Expression injection in -only workflows on protected branches
push - input injection where all callers are internal
workflow_call - Secrets in /
workflow_dispatch-only workflowsschedule
仅上报可被外部攻击者利用的漏洞——外部攻击者指没有仓库写入权限的人员。攻击者可从fork仓库提交PR、创建issue、发表评论,但无法推送代码到分支、触发或其他手动工作流。
workflow_dispatch不要标记需要写入权限才能利用的漏洞:
- 输入注入 — 需要写入权限才能触发
workflow_dispatch - 受保护分支上仅触发的工作流中的表达式注入
push - 调用方均为内部的输入注入
workflow_call - 仅/
workflow_dispatch触发的工作流中的密钥schedule
Confidence
置信度
Report only HIGH and MEDIUM confidence findings. Do not report theoretical issues.
| Confidence | Criteria | Action |
|---|---|---|
| HIGH | Traced the full attack path, confirmed exploitable | Report with exploitation scenario and fix |
| MEDIUM | Attack path partially confirmed, uncertain link | Report as needs verification |
| LOW | Theoretical or mitigated elsewhere | Do not report |
For each HIGH finding, provide all five elements:
- Entry point — How does the attacker get in? (fork PR, issue comment, branch name, etc.)
- Payload — What does the attacker send? (actual code/YAML/input)
- Execution mechanism — How does the payload run? (expression expansion, checkout + script, etc.)
- Impact — What does the attacker gain? (token theft, code execution, repo write access)
- PoC sketch — Concrete steps an attacker would follow
If you cannot construct all five, report as MEDIUM (needs verification).
仅上报高和中置信度的发现,不要上报理论上存在的问题。
| 置信度 | 判定标准 | 处理方式 |
|---|---|---|
| 高 | 已追踪完整攻击路径,确认可利用 | 上报时附带利用场景和修复方案 |
| 中 | 攻击路径部分确认,存在不确定环节 | 标记为待验证后上报 |
| 低 | 理论存在风险或已在其他环节被缓解 | 不上报 |
针对每一项高置信度发现,需提供以下全部五个要素:
- 入口点 — 攻击者如何入侵?(fork提交的PR、issue评论、分支名等)
- Payload — 攻击者发送的内容是什么?(实际代码/YAML/输入内容)
- 执行机制 — Payload如何被执行?(表达式展开、拉取代码+运行脚本等)
- 影响 — 攻击者可获得什么权限?(令牌窃取、代码执行、仓库写入权限)
- PoC概要 — 攻击者需执行的具体步骤
如果你无法凑齐全部五个要素,标记为中置信度(待验证)上报。
Step 1: Classify Triggers and Load References
步骤1:分类触发器并加载参考资料
For each workflow, identify triggers and load the appropriate reference:
| Trigger / Pattern | Load Reference |
|---|---|
| |
| |
| |
| PATs / deploy keys / elevated credentials | |
| Checkout PR code + config file loading | |
| Third-party actions (especially unpinned) | |
| |
| Self-hosted runners, cache/artifact usage | |
| Any confirmed finding | |
Load references selectively — only what's relevant to the triggers found.
针对每个工作流,识别触发器并加载对应的参考资料:
| 触发器/模式 | 加载的参考资料 |
|---|---|
| |
带命令解析的 | |
| |
| PAT/部署密钥/高权限凭证 | |
| 拉取PR代码+加载配置文件 | |
| 第三方action(尤其是未固定版本的) | |
| |
| 自托管runner、缓存/制品使用 | |
| 任何已确认的发现 | |
有选择地加载参考资料——仅加载与发现的触发器相关的内容即可。
Step 2: Check for Vulnerability Classes
步骤2:检查漏洞类型
Check 1: Pwn Request
检查1:Pwn请求
Does the workflow use AND check out fork code?
pull_request_target- Look for with
actions/checkoutpointing to PR headref: - Look for local actions () that would come from the fork
./.github/actions/ - Check if any step executes code from the checked-out PR
run:
工作流是否使用了且拉取了fork的代码?
pull_request_target- 查找指向PR HEAD的
ref:步骤actions/checkout - 查找可能来自fork的本地action()
./.github/actions/ - 检查是否有步骤执行了拉取的PR中的代码
run:
Check 2: Expression Injection
检查2:表达式注入
Are expressions used inside blocks in externally-triggerable workflows?
${{ }}run:- Map every expression in every
${{ }}steprun: - Confirm the value is attacker-controlled (PR title, branch name, comment body — not numeric IDs, SHAs, or repository names)
- Confirm the expression is in a block, not
run:,if:, or job-levelwith:env:
可被外部触发的工作流的块中是否使用了表达式?
run:${{ }}- 枚举所有步骤中的每一个
run:表达式${{ }} - 确认表达式的值是攻击者可控的(PR标题、分支名、评论内容,而非数字ID、SHA或仓库名)
- 确认表达式位于块中,而非
run:、if:或任务级别的with:中env:
Check 3: Unauthorized Command Execution
检查3:未授权命令执行
Does an -triggered workflow execute commands without authorization?
issue_comment- Is there an check?
author_association - Can any GitHub user trigger the command?
- Does the command handler also use injectable expressions?
由触发的工作流是否在未授权的情况下执行命令?
issue_comment- 是否有校验?
author_association - 任意GitHub用户都可以触发该命令吗?
- 命令处理逻辑是否同时使用了可注入的表达式?
Check 4: Credential Escalation
检查4:凭证提权
Are elevated credentials (PATs, deploy keys) accessible to untrusted code?
- What's the blast radius of each secret?
- Could a compromised workflow steal long-lived tokens?
高权限凭证(PAT、部署密钥)是否可被不可信代码访问?
- 每个密钥的影响范围有多大?
- 被攻陷的工作流是否可以窃取长期有效的令牌?
Check 5: Config File Poisoning
检查5:配置文件投毒
Does the workflow load configuration from PR-supplied files?
- AI agent instructions: ,
CLAUDE.md,AGENTS.md.cursorrules - Build configuration: , shell scripts
Makefile
工作流是否从PR提供的文件中加载配置?
- AI Agent指令:、
CLAUDE.md、AGENTS.md.cursorrules - 构建配置:、shell脚本
Makefile
Check 6: Supply Chain
检查6:供应链风险
Are third-party actions securely pinned?
第三方action是否被安全地固定了版本?
Check 7: Permissions and Secrets
检查7:权限与密钥
Are workflow permissions minimal? Are secrets properly scoped?
工作流权限是否遵循最小权限原则?密钥的作用域是否合理?
Check 8: Runner Infrastructure
检查8:Runner基础设施
Are self-hosted runners, caches, or artifacts used securely?
自托管runner、缓存、制品的使用是否安全?
Safe Patterns (Do Not Flag)
安全模式(不要标记)
Before reporting, check if the pattern is actually safe:
| Pattern | Why Safe |
|---|---|
| Never executes attacker code |
| Numeric only — not injectable |
| Repo owner controls this |
| Not an expression injection vector |
| Evaluated by Actions runtime, not shell |
| Passed as string parameters, not shell-evaluated |
| Actions pinned to full SHA | Immutable reference |
| Runs in fork context with read-only token |
Any expression in | Requires write access — outside threat model |
Key distinction: is dangerous in blocks (shell expansion) but safe in , , and at the job/step level (Actions runtime evaluation).
${{ }}run:if:with:env:上报前,先检查对应模式是否确实是安全的:
| 模式 | 安全原因 |
|---|---|
不拉取fork代码的 | 永远不会执行攻击者的代码 |
| 仅为数字,无法注入 |
| 由仓库所有者控制 |
| 不是表达式注入的攻击向量 |
| 由Actions runtime求值,而非shell执行 |
| 作为字符串参数传递,不会被shell求值 |
| 固定到完整SHA的action | 不可变的引用 |
| 在fork上下文中运行,仅持有只读令牌 |
| 需要写入权限,不在威胁模型范围内 |
关键区别:在块中是危险的(会触发shell展开),但在任务/步骤级别的、、中是安全的(由Actions runtime求值)。
${{ }}run:if:with:env:Step 3: Validate Before Reporting
步骤3:上报前校验
Before including any finding, read the actual workflow YAML and trace the complete attack path:
- Read the full workflow — don't rely on grep output alone
- Trace the trigger — confirm the event and check conditions that gate execution
if: - Trace the expression/checkout — confirm it's in a block or actually references fork code
run: - Confirm attacker control — verify the value maps to something an external attacker sets
- Check existing mitigations — env var wrapping, author_association checks, restricted permissions, SHA pinning
If any link is broken, mark MEDIUM (needs verification) or drop the finding.
If no checks produced a finding, report zero findings. Do not invent issues.
上报任何发现前,请阅读完整的工作流YAML文件,追踪完整的攻击路径:
- 阅读完整工作流 — 不要仅依赖grep输出
- 追踪触发器 — 确认触发事件,检查控制执行的条件
if: - 追踪表达式/代码拉取逻辑 — 确认它位于块中,或确实引用了fork的代码
run: - 确认攻击者可控 — 验证对应值是外部攻击者可以设置的
- 检查现有防护措施 — 环境变量封装、校验、权限限制、SHA版本固定
author_association
如果任何环节不成立,标记为中置信度(待验证)或放弃上报该发现。
如果所有检查都没有发现问题,上报零漏洞。不要虚构问题。
Step 4: Report Findings
步骤4:上报发现
markdown
undefinedmarkdown
undefinedGitHub Actions Security Review
GitHub Actions安全审查
Findings
发现的漏洞
[GHA-001] [Title] (Severity: Critical/High/Medium)
[GHA-001] [漏洞标题](严重程度:严重/高/中)
- Workflow:
.github/workflows/release.yml:15 - Trigger:
pull_request_target - Confidence: HIGH — confirmed through attack path tracing
- Exploitation Scenario:
- [Step-by-step attack]
- Impact: [What attacker gains]
- Fix: [Code that fixes the issue]
- 工作流:
.github/workflows/release.yml:15 - 触发器:
pull_request_target - 置信度: 高 — 已通过攻击路径追踪确认
- 利用场景:
- [分步攻击步骤]
- 影响: [攻击者可获得的权限]
- 修复方案: [修复问题的代码]
Needs Verification
待验证
[MEDIUM confidence items with explanation of what to verify]
[中置信度项,附带需要验证的内容说明]
Reviewed and Cleared
已审查无风险
[Workflows reviewed and confirmed safe]
If no findings: "No exploitable vulnerabilities identified. All workflows reviewed and cleared."[已审查并确认安全的工作流]
如果没有发现漏洞,返回:"未发现可利用的漏洞。所有工作流已审查通过。"