mcpField
S
securing-github-actions-workflows

securing-github-actions-workflows

github.com/mukul975安全35.2k202 次安装8 周前更新
代码仓库

关于 securing-github-actions-workflows

面向使用 GitHub Actions 的团队的工作流安全加固技能,提供降低令牌权限、固定 Action 版本、处理不可信输入和保护部署密钥等步骤。重点是防范供应链风险与工作流注入。

主要功能

  1. 01将 Actions 固定到 SHA
  2. 02限制 GITHUB_TOKEN 权限
  3. 03防止不可信输入触发脚本注入
  4. 04安全处理 Fork 拉取请求
  5. 05保护密钥并设置环境审批
  6. 06通过 CODEOWNERS 管控工作流变更

适用场景

  1. 01降低第三方 Action 被篡改的风险
  2. 02保护处理生产部署的工作流
  3. 03阻止拉取请求内容触发命令注入
  4. 04要求审查工作流文件变更

安装

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

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill securing-github-actions-workflows

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

包含的文件

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

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py
process.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 的仓库会自动拉取恶意版本。

方法:

  1. 立即在所有仓库中将所有 action 固定到 SHA 摘要
  2. 为 github-actions 生态系统配置 Dependabot 以管理 SHA 更新
  3. 限制 GITHUB_TOKEN 权限,使即使受损的 action 也只有最小访问权限
  4. 添加 StepSecurity harden-runner 以检测异常出站网络调用
  5. 审查所有第三方 action,并将不必要的替换为内联脚本
  6. 要求对 .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