关于 securing-github-actions-workflows
面向使用 GitHub Actions 的团队的工作流安全加固技能,提供降低令牌权限、固定 Action 版本、处理不可信输入和保护部署密钥等步骤。重点是防范供应链风险与工作流注入。
主要功能
- 01将 Actions 固定到 SHA
- 02限制 GITHUB_TOKEN 权限
- 03防止不可信输入触发脚本注入
- 04安全处理 Fork 拉取请求
- 05保护密钥并设置环境审批
- 06通过 CODEOWNERS 管控工作流变更
适用场景
- 01降低第三方 Action 被篡改的风险
- 02保护处理生产部署的工作流
- 03阻止拉取请求内容触发命令注入
- 04要求审查工作流文件变更
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill securing-github-actions-workflows安装后在 Claude Code 中输入/securing-github-actions-workflows确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEassets/template.mdreferences/api-reference.mdstandards.mdworkflows.mdscripts/agent.pyprocess.py详细介绍
保护 GitHub Actions 工作流
何时使用
- 当 GitHub Actions 是 CI/CD 平台,且工作流需要加固以抵御供应链攻击时
- 当工作流处理密钥、部署到生产环境或拥有提升的权限时
- 当防止通过不可信的 PR 标题、分支名或提交信息进行脚本注入时
- 当需要对工作流修改设置审计追踪和审批关卡时
- 当第三方 action 通过可变版本标签构成供应链风险时
不要使用于保护其他 CI/CD 平台(参见平台专属加固指南)、应用程序漏洞扫描(使用 SAST/DAST),或代码中的密钥检测(使用 Gitleaks)。
前置条件
- 已启用 GitHub Actions 的 GitHub 仓库
- 用于组织级设置的 GitHub 组织管理员访问权限
- 了解 GitHub Actions 工作流语法和事件
工作流
步骤 1:将 Action 固定到 SHA 摘要
# INSECURE: Mutable tag can be overwritten by attacker
- uses: actions/checkout@v4
# SECURE: Pinned to immutable SHA digest
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
# Use Dependabot to auto-update pinned SHAs
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "ci"
步骤 2:最小化 GITHUB_TOKEN 权限
# Set restrictive default permissions at workflow level
name: CI Pipeline
permissions: {} # Start with no permissions
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read # Only what's needed
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
deploy:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
permissions:
contents: read
deployments: write
id-token: write # For OIDC-based cloud auth
steps:
- name: Deploy
run: echo "deploying"
步骤 3:防止脚本注入
# VULNERABLE: User-controlled input in run step
- run: echo "PR title is ${{ github.event.pull_request.title }}"
# SECURE: Use environment variable (properly escaped by shell)
- name: Process PR
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
run: |
echo "PR title is ${PR_TITLE}"
echo "PR body is ${PR_BODY}"
# SECURE: Use actions/github-script for complex operations
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
with:
script: |
const title = context.payload.pull_request.title;
console.log(`PR title: ${title}`);
步骤 4:安全处理 Fork 拉取请求
# DANGEROUS: pull_request_target runs with base repo permissions
# on: pull_request_target # AVOID unless absolutely necessary
# SAFE: pull_request runs in fork context with limited permissions
on:
pull_request:
branches: [main]
# If pull_request_target is required, never checkout PR code:
on:
pull_request_target:
types: [labeled]
jobs:
safe-job:
if: contains(github.event.pull_request.labels.*.name, 'safe-to-test')
runs-on: ubuntu-latest
permissions:
contents: read
steps:
# NEVER do: actions/checkout with ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
# This checks out the BASE branch, not the PR
步骤 5:保护密钥和环境变量
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # Requires approval
steps:
- name: Deploy with secret
env:
# Secrets are masked in logs automatically
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: |
# Never echo secrets
# echo "$DEPLOY_KEY" # BAD
deploy-tool --key-file <(echo "$DEPLOY_KEY")
- name: Audit secret access
run: |
# Log that secret was used without exposing it
echo "::notice::Deploy key accessed for production deployment"
步骤 6:实施工作流变更控制
# Require CODEOWNERS approval for workflow changes
# .github/CODEOWNERS
.github/workflows/ @security-team @platform-team
.github/actions/ @security-team @platform-team
# Organization settings:
# 1. Settings > Actions > General > Fork PR policies
# - Require approval for first-time contributors
# - Require approval for all outside collaborators
# 2. Settings > Actions > General > Workflow permissions
# - Read repository contents and packages permissions
# - Do NOT allow GitHub Actions to create and approve PRs
关键概念
| 术语 | 定义 |
|---|---|
| SHA 固定 | 通过不可变的提交 SHA 而非可变版本标签来引用 GitHub Actions |
| 脚本注入 | 将不可信输入(PR 标题、分支名)插值到 shell 命令中的攻击 |
| GITHUB_TOKEN | 自动生成的令牌,具有限定于当前仓库的可配置权限 |
| pull_request_target | 危险的事件触发器,在 fork PR 上以完整权限在基础仓库上下文中运行 |
| 环境保护 | GitHub 功能,要求访问环境的作业运行前需手动审批 |
| CODEOWNERS | 定义特定路径(包括工作流文件)所需审查者的文件 |
| OIDC 联合 | 使用 GitHub 的 OIDC 令牌向云提供商进行身份验证,而无需存储长期凭证 |
工具与系统
- Dependabot:自动依赖更新器,保持固定的 action SHA 为最新
- StepSecurity Harden Runner:GitHub Action,监控并限制工作流的出站网络调用
- actionlint:GitHub Actions 工作流文件的 linter,可检测安全问题
- allstar:OpenSSF 的 GitHub App,对仓库强制执行安全策略
- scorecard:OpenSSF 工具,评估包括 CI/CD 在内的供应链安全实践
常见场景
场景:通过受损的第三方 Action 防止供应链攻击
背景:一个广泛使用的 GitHub Action 被入侵,其 v3 标签被更新为包含凭证窃取代码。使用 @v3 的仓库会自动拉取恶意版本。
方法:
- 立即在所有仓库中将所有 action 固定到 SHA 摘要
- 为 github-actions 生态系统配置 Dependabot 以管理 SHA 更新
- 限制 GITHUB_TOKEN 权限,使即使受损的 action 也只有最小访问权限
- 添加 StepSecurity harden-runner 以检测异常出站网络调用
- 审查所有第三方 action,并将不必要的替换为内联脚本
- 要求对 .github/workflows/ 的任何更改需 CODEOWNERS 审批
陷阱:没有 Dependabot 的 SHA 固定意味着错过 action 的合法安全更新。过于严格的权限可能破坏合法工作流。使用 pull_request_target 进行基于标签的门控,如果工作流检出 PR 代码,仍会暴露密钥。
输出格式
GitHub Actions Security Audit
================================
Repository: org/web-application
Date: 2026-02-23
WORKFLOW ANALYSIS:
Total workflows: 8
Total action references: 34
SHA PINNING:
[FAIL] 12/34 actions use mutable tags instead of SHA digests
- .github/workflows/ci.yml: actions/setup-node@v4
- .github/workflows/deploy.yml: aws-actions/configure-aws-credentials@v4
PERMISSIONS:
[FAIL] 3/8 workflows have no explicit permissions (inherit default)
[WARN] 1/8 workflows request write-all permissions
SCRIPT INJECTION:
[FAIL] 2 workflow steps interpolate user input directly
- .github/workflows/pr-check.yml:23: ${{ github.event.pull_request.title }}
SECRETS:
[PASS] No secrets exposed in workflow logs
[PASS] All production deployments use environment protection
SCORE: 6/10 (Remediate 5 HIGH findings)
评论
支持 Markdown