GitHub Actions 安全与 Secret 管理:权限控制、OIDC 认证、审计与最佳实践

GitHub Actions 安全深度指南:最小权限原则、Secrets 管理策略、OIDC 免密云认证(AWS/Azure/GCP)、Artifact 安全、权限审计、依赖供应链安全(Dependabot/CodeQL)、Self-hosted Runner 隔离,以及常见安全漏洞与防护。

CI/CD 管道是供应链攻击的主要目标。源码、构建环境、密钥一旦泄露,攻击者可以直接植入恶意代码、窃取数据或劫持部署。本文从权限配置到认证机制,构建 GitHub Actions 的完整安全防线。


一、最小权限原则(Principle of Least Privilege)

1.1 默认关闭权限,按需分配

# ❌ 危险:默认赋予所有权限
# (不设置 permissions 时,默认读写所有内容)

# ✅ 推荐:显式声明最小权限
permissions:
  contents: read           # 只读代码
  pull-requests: write     # 仅 PR 操作
  id-token: write          # OIDC Token(云认证)

jobs:
  deploy:
    permissions:
      contents: read
      packages: write      # 推送容器镜像
      id-token: write

权限级别

级别作用域说明
read只读safest,默认首选
write读写需要修改资源时使用
none无权限显式禁用

1.2 组织级权限策略

# 在组织级别限制默认权限
# GitHub Organization → Settings → Actions → General
# Default workflow permissions: Read repository contents and packages permissions

二、Secrets 管理策略

2.1 Secret vs Variable:明确区分

类型存储方式日志显示适用
Secrets加密存储❌ 隐藏(显示为 ***API Key、Token、密码
Variables明文存储✅ 可见环境名、Region、版本号

2.2 Secret 注入正确方式

# ✅ 正确:env 注入,避免命令行回显
jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      API_KEY: ${{ secrets.API_KEY }}
    steps:
      - run: |
          curl -H "Authorization: Bearer $API_KEY" https://api.example.com

# ❌ 危险:直接在命令行使用(部分 CI 系统会回显)
# - run: curl -H "Authorization: Bearer ${{ secrets.API_KEY }}" ...

2.3 Secret 轮转策略

Secret 类型轮转周期方式
云平台 Access Key90 天IAM 控制台重新生成
npm Token180 天npm 网站重新生成
Docker Hub Token90 天Account Settings → Security
SSH 密钥180 天ssh-keygen 重新生成

三、OIDC 免密云认证

3.1 为什么用 OIDC?

传统方式将云服务密钥(AWS Access Key)存为 Secrets,存在泄露风险。OIDC(OpenID Connect)让 GitHub Actions 通过 JWT Token 临时换取云服务的访问凭证,无需长期密钥

3.2 AWS OIDC 配置

permissions:
  id-token: write
  contents: read

jobs:
  deploy-aws:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
          aws-region: us-east-1
          role-duration-seconds: 1200  # 临时凭证有效期

      - run: aws s3 sync ./dist s3://my-bucket

AWS IAM 信任策略

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Federated": "arn:aws:iam::123456789:oidc-provider/token.actions.githubusercontent.com" },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" },
      "StringLike": { "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*" }
    }
  }]
}

3.3 Azure OIDC

- name: Azure Login
  uses: azure/login@v2
  with:
    client-id: ${{ secrets.AZURE_CLIENT_ID }}
    tenant-id: ${{ secrets.AZURE_TENANT_ID }}
    subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

3.4 GCP OIDC

- name: GCP Auth
  uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: 'projects/123/locations/global/workloadIdentityPools/github-pool/providers/github-provider'
    service_account: 'github-actions@my-project.iam.gserviceaccount.com'

四、依赖与供应链安全

4.1 Dependabot 自动化依赖更新

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10
    reviewers:
      - "octocat"

4.2 CodeQL 安全扫描

name: CodeQL
on:
  push: { branches: [main] }
  pull_request: { branches: [main] }
  schedule: [ cron: '0 9 * * 1' ]

jobs:
  analyze:
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3
        with:
          languages: javascript, typescript
      - uses: github/codeql-action/analyze@v3

4.3 npm audit 在 CI 中

- run: npm audit --audit-level=moderate
- run: npm audit fix --dry-run  # 查看建议修复

4.4 SLSA 来源证明

- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
  with:
    base64-subjects: "${{ hashFiles('dist/**') }}"

五、Self-hosted Runner 安全

5.1 Runner 隔离策略

隔离级别方法效果
用户隔离每个 runner 独立用户防止跨项目访问
容器隔离Docker-in-Docker每个 job 独立容器
VM 隔离每次启动新 VM最强隔离,启动较慢
临时 Runner用完即销毁最高安全

5.2 Runner 标签策略

jobs:
  deploy-production:
    runs-on: [self-hosted, production]  # 标签限制

六、常见安全漏洞与防护

漏洞原因防护
秘密泄露硬编码 API Key使用 Secrets + OIDC
恶意 Action使用未审核第三方 Action固定 commit SHA,pin 版本
脚本注入${{ github.head_ref }} 在命令行中使用env 注入,避免字符串拼接
权限提升workflow 具有过高权限permissions: contents: read
Artifact 泄露敏感文件包含在 Artifact 中.gitignore + artifact 路径限制

七、安全审计检查清单

  • 组织级别设置默认只读权限
  • 所有工作流显式声明 permissions
  • Secrets 使用 env: 注入而非命令行
  • 使用 OIDC 替代长期云密钥
  • 第三方 Action 固定到 commit SHA
  • Dependabot 启用自动更新
  • CodeQL 启用安全扫描
  • npm audit 在 CI 中阻塞高危漏洞
  • Self-hosted Runner 启用标签隔离
  • 定期轮转 Secrets(90 天)

相关阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「saas」更多文章