mcpField
G
github-actions-hardening

github-actions-hardening

github.com/github安全40.5k2.2k 次安装今天更新
代码仓库

关于 github-actions-hardening

面向 GitHub Actions 工作流作者和审查者的安全审计技能,聚焦触发器权限、表达式注入、令牌权限及 Action 固定版本等工作流特有风险。

主要功能

  1. 01判断触发器的信任级别与权限
  2. 02检查表达式导致的脚本注入
  3. 03审计令牌权限与机密处理
  4. 04检查 Action 引用及 SHA 固定
  5. 05按严重级别报告问题并给出修复

适用场景

  1. 01合并前审计现有工作流
  2. 02加固使用特权触发器的工作流
  3. 03检查令牌范围与机密处理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/github/awesome-copilot --skill github-actions-hardening

安装后在 Claude Code 中输入/github-actions-hardening确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
injection.md
permissions-and-tokens.md
report-format.md
supply-chain.md
triggers-and-privilege.md

详细介绍

GitHub Actions 安全加固

一个专注于 GitHub Actions 工作流的安全审查工具。它针对的是 Actions 特有 的威胁模型——即信任边界存在于触发器类型、令牌作用域和字符串插值之中——而不是通用安全扫描器所关注的应用程序代码漏洞。大多数工作流风险对语言层面的 linter 来说是不可见的,因为危险的代码就是 YAML 本身,以及 GitHub 在你的脚本运行之前将 ${{ }} 表达式展开进 shell 的方式。

何时使用本技能

当请求涉及以下内容时使用本技能:

  • 审查、审计或加固 .github/workflows/ 下的任何文件
  • 编写新工作流,并希望其默认就是安全的
  • 使用了 pull_request_target、workflow_run 或 issue_comment 触发器的工作流
  • 关于 GITHUB_TOKEN 权限或 permissions: 键的问题
  • 将 action 固定到 commit SHA、tag 还是 branch
  • 在 run: 步骤中处理不受信任的输入(issue 标题、PR 正文、分支名、提交信息)
  • 从 Actions 进行 OIDC / 云认证,或 CI 中的密钥处理
  • 公共仓库上的自托管 runner
  • 任何类似"这个工作流安全吗?"、"加固我的 CI"或"审查这个 GitHub Action"的请求

核心洞察

在工作流中,${{ <expr> }} 会在 shell 执行脚本 之前 被 runner 展开进脚本中。 因此,像这样的步骤:

- run: echo "Title: ${{ github.event.issue.title }}"

并不是在传递一个变量——它是在 把攻击者控制的文本直接粘贴进你的 shell 命令。一个标题为 "; <attacker-command> # 的 issue 会被拼接进脚本并执行。这一单一机制是现实世界中最常见的 Actions 漏洞,而模型会经常性地生成它。把每一个包含外部贡献者可影响数据的 ${{ }} 都视为代码注入的汇聚点。

执行工作流

对每个被审查的工作流,按顺序执行以下步骤。

步骤 1 — 梳理触发器与信任级别

阅读每一个 on: 触发器,并对工作流的权限进行分类:

  • push、pull_request(来自同一仓库)→ 以贡献者自身的信任级别运行
  • 来自 fork 的 pull_request → 以 只读 令牌运行,无密钥(设计上安全)
  • pull_request_target、workflow_run、issue_comment、issues → 在 基础仓库 的上下文中运行,拥有 读/写令牌和对密钥的完全访问权限,但可以被 外部贡献者触发。这些是危险的触发器。

阅读 references/triggers-and-privilege.md 以获取完整的信任矩阵。

步骤 2 — 搜寻脚本注入

对每一个 run: 块、actions/github-script 中的每一个 script:,以及自定义 action 的每一个输入,列出所有 ${{ }} 表达式,并检查其中是否有任何表达式会解析为攻击者可控制的数据。高风险上下文包括:

  • github.event.issue.title、github.event.issue.body
  • github.event.pull_request.title、github.event.pull_request.body、.head.ref、.head.label
  • github.event.comment.body、github.event.review.body
  • github.event.pages.*.page_name、github.event.commits.*.message、github.event.head_commit.*
  • github.head_ref 以及 fork 作者可以设置的任何 github.event.* 字段

阅读 references/injection.md 以获取完整的汇聚点列表及安全模式修复方法。

步骤 3 — 检查特权触发器不会执行不受信任的代码

如果 pull_request_target 或 workflow_run 工作流检出 PR/fork 代码 (ref: ${{ github.event.pull_request.head.sha }})然后运行它(构建、测试、安装脚本、带生命周期脚本的 npm install 等),那就是针对特权令牌的远程代码执行。将其标记为 CRITICAL。安全模式是拆分为两个工作流:一个无特权的 pull_request 工作流运行不受信任的代码,另一个有特权的 workflow_run 工作流只消费其结果。

第 4 步 — 审计 permissions:
  • 如果没有 permissions: 块,工作流会继承仓库默认权限,这可能对所有内容都是读/写。标记它。
  • 建议使用顶层 permissions: {}(全部拒绝)或 contents: read,然后按 job 授予最小权限(例如仅在负责评论的 job 上使用 pull-requests: write)。
  • 标记任何 permissions: write-all 或步骤实际并不需要的宽泛 write 权限范围。

阅读 references/permissions-and-tokens.md 了解按权限范围的指导以及 OIDC 设置。

第 5 步 — 审计 Action 引用(供应链)

对于每一个 uses::

  • 第三方 action(不是 actions/* 或 github/*)必须固定到完整的 40 字符 commit SHA,而不是标签或分支。标签和分支是可变的;被攻陷的上游 action 可以把 v1 重写为使用你的 token 和 secret 运行的恶意代码。
  • 第一方 actions/* 风险较低,但固定 SHA 仍是强化后的推荐做法。
  • 将 @main、@master 或任何分支引用标记为 HIGH — 那是“latest”,随时可能在你不知情的情况下发生变化。
  • 在行尾注释中注明人类可读的版本:uses: foo/bar@<sha> # v2.1.0。

阅读 references/supply-chain.md 了解固定、用于 actions 的 Dependabot,以及 artifact/cache 风险。

第 6 步 — 检查 Secret 和输出处理
  • 不得回显、打印或将 secret 写入日志;在涉及 secret 的步骤中不得使用 set -x / bash -x。
  • 不得将 secret 传递给运行不受信任代码的步骤或不受信任的第三方 action。
  • 写入 $GITHUB_ENV 或 $GITHUB_OUTPUT 的不受信任多行数据可能注入环境变量或步骤输出 — 请使用随机分隔符 heredoc 形式,并且绝不写入原始用户输入。
  • actions/checkout 默认会在磁盘上留下 token;当 job 之后运行不受信任代码时,请设置 persist-credentials: false。
第 7 步 — 生成报告

使用 references/report-format.md 中的格式输出发现:首先是严重性汇总表,然后按问题类型分组的发现,包含文件、确切的违规 YAML、用简明英语说明的风险,以及具体的修改前后对比。绝不自动应用更改 — 将其呈现以供审查。

严重性指南

严重性含义示例
🔴 CRITICAL外部贡献者可触发的 token/secret 窃取或 RCEpull_request_target 检出并运行 fork 代码;在特权触发器上的 run: 中使用 ${{ github.event.* }}
🟠 HIGH可被利用的供应链或权限范围问题使用可变标签/分支的第三方 action;write-all 权限;issue_comment 上的注入汇聚点
🟡 MEDIUM有条件或可链式利用的风险缺少 permissions: 块;非 fork PR 作者可触及 secret
🔵 LOW强化缺口,直接风险较低第一方 action 未固定 SHA;在非特权 job 上保留 persist-credentials 默认值
⚪ INFO观察项,而非漏洞固定的 SHA 旁边缺少版本注释

输出规则

  • 始终先展示发现汇总表(按严重性计数)。
  • 按问题类型分组,而不是按文件分组。
  • 务必精确 — 引用违规行并给出行位置。
  • 始终为每个 CRITICAL/HIGH 配上一段具体的修正 YAML 片段。
  • 绝不仅因为 fork 的 pull_request 运行不受信任代码就声称它危险 — 它没有 secret,并且使用只读 token。请将 CRITICAL 保留给特权触发器。
  • 如果工作流已经强化,请说明,并列出已检查的内容。

参考文件

按需加载以下文件:

  • references/triggers-and-privilege.md — 每个触发器的信任矩阵,为什么 pull_request_target 和 workflow_run 具有特权,以及双工作流安全模式。
    • 搜索模式:pull_request_target、workflow_run、issue_comment、fork、secrets、read-only token、trust boundary
  • references/injection.md — 攻击者可控的 ${{ }} 上下文完整列表,以及针对每个 汇聚点(run、github-script、action 输入)的 env: 变量安全模式。
    • 搜索模式:script injection、github.event、head_ref、issue title、env、intermediate variable、actions/github-script
  • references/permissions-and-tokens.md — GITHUB_TOKEN 作用域、按作业类型划分的最小权限 permissions: 配方,以及使用 OIDC 进行云认证而非长期有效的密钥。
    • 搜索模式:permissions、GITHUB_TOKEN、write-all、contents: read、id-token、OIDC、least privilege
  • references/supply-chain.md — 对第三方 action 进行 SHA 固定、为 github-actions 配置 Dependabot、 跨 workflow_run 的产物与缓存投毒,以及自托管 runner 的暴露风险。
    • 搜索模式:SHA pin、uses、mutable tag、Dependabot、download-artifact、cache、self-hosted runner
  • references/report-format.md — 输出模板:摘要表格、发现卡片,以及修复前后的 代码块。
    • 搜索模式:report、format、finding、summary、remediation、before、after

评论

支持 Markdown