gha-security-review

gha-security-review

热门

对GitHub Actions工作流进行安全审查,发现可利用的漏洞。当被要求“审查GitHub Actions”、“审计工作流”、“检查CI安全”、“GHA安全”、“工作流安全审查”,或审查.github/workflows/中的pwn请求、表达式注入、凭证窃取和供应链攻击时使用。专注于利用,提供具体的PoC场景。

883Star
45Fork
更新于 2026/7/23
SKILL.md
readonly只读
name
gha-security-review
description

对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.mdAGENTS.mdMakefile.github/下的shell脚本

不在范围内

  • 其他仓库中的工作流(仅注明依赖关系)
  • GitHub App安装权限(如果相关则注明)

威胁模型

仅报告外部攻击者可利用的漏洞——即没有仓库写入权限的人。攻击者可以从fork打开PR、创建issue和发表评论。他们不能推送到分支、触发workflow_dispatch或触发手动工作流。

不要标记需要写入权限才能利用的漏洞:

  • workflow_dispatch输入注入——需要写入权限才能触发
  • 受保护分支上仅push触发的工作流中的表达式注入
  • 所有调用者均为内部时的workflow_call输入注入
  • workflow_dispatch/schedule工作流中的密钥

置信度

仅报告置信度的发现。不要报告理论性问题。

置信度 标准 操作
追踪了完整攻击路径,确认可利用 报告并附带利用场景和修复方案
攻击路径部分确认,存在不确定环节 报告为需要验证
理论性或已在其他地方缓解 不报告

对于每个高置信度发现,提供全部五个要素:

  1. 入口点 — 攻击者如何进入?(fork PR、issue评论、分支名称等)
  2. 载荷 — 攻击者发送什么?(实际代码/YAML/输入)
  3. 执行机制 — 载荷如何运行?(表达式展开、检出+脚本等)
  4. 影响 — 攻击者获得什么?(令牌窃取、代码执行、仓库写入权限)
  5. 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
检出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并且检出了fork代码?

  • 查找带有指向PR头的ref:actions/checkout
  • 查找来自fork的本地操作(./.github/actions/
  • 检查是否有run:步骤执行了来自检出PR的代码

检查2:表达式注入

在外部可触发的工作流中,run:块内是否使用了${{ }}表达式?

  • 映射每个run:步骤中的每个${{ }}表达式
  • 确认该值由攻击者控制(PR标题、分支名称、评论正文——而不是数字ID、SHA或仓库名称)
  • 确认表达式在run:块中,而不是if:with:或作业级别的env:

检查3:未授权命令执行

issue_comment触发的工作流是否在未授权的情况下执行命令?

  • 是否有author_association检查?
  • 任何GitHub用户都能触发该命令吗?
  • 命令处理器是否也使用了可注入的表达式?

检查4:凭证升级

提升的凭证(PAT、部署密钥)是否可被不受信任的代码访问?

  • 每个密钥的爆炸半径是多少?
  • 被攻陷的工作流能否窃取长期令牌?

检查5:配置文件投毒

工作流是否从PR提供的文件加载配置?

  • AI代理指令:CLAUDE.mdAGENTS.md.cursorrules
  • 构建配置:Makefile、shell脚本

检查6:供应链

第三方操作是否安全地固定了版本?

检查7:权限和密钥

工作流权限是否最小化?密钥是否适当限定范围?

检查8:运行器基础设施

自托管运行器、缓存或制品是否安全使用?

安全模式(不要标记)

在报告之前,检查模式是否实际上是安全的:

模式 为什么安全
pull_request_target 且未检出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并追踪完整的攻击路径:

  1. 阅读完整工作流 — 不要仅依赖grep输出
  2. 追踪触发器 — 确认事件并检查控制执行的if:条件
  3. 追踪表达式/检出 — 确认它在run:块中或实际引用了fork代码
  4. 确认攻击者控制 — 验证该值映射到外部攻击者可以设置的内容
  5. 检查现有缓解措施 — 环境变量包装、author_association检查、受限权限、SHA固定

如果任何环节断裂,标记为中置信度(需要验证)或放弃该发现。

如果所有检查均未产生发现,报告零发现。不要编造问题。

步骤4:报告发现

## GitHub Actions 安全审查

### 发现

#### [GHA-001] [标题] (严重性:严重/高/中)
- **工作流**:`.github/workflows/release.yml:15`
- **触发器**:`pull_request_target`
- **置信度**:高——通过攻击路径追踪确认
- **利用场景**:
  1. [逐步攻击]
- **影响**:[攻击者获得什么]
- **修复**:[修复问题的代码]

### 需要验证
[中置信度项目,附需要验证的解释]

### 已审查并确认安全
[已审查并确认安全的工作流]

如果没有发现:"未发现可利用的漏洞。所有工作流已审查并确认安全。"