什么是 CI/CD 安全十大风险?

OWASP 十大 CI/CD 安全风险确定了持续集成和持续交付管道中最重要的安全风险。CI/CD 管道是高价值目标,因为它们可以直接访问源代码、机密和生产环境。本指南涵盖流量控制、身份管理、依赖性攻击、管道中毒等内容。

1️⃣ CICD-SEC-1 - 流量控制机制不足

Critical

概述

流量控制机制的不足使得攻击者可以在没有适当审查或批准关卡的情况下通过 CI/CD 管道推送恶意代码。这包括绕过分支保护规则、缺少所需的审批,以及缺乏对谁可以触发部署到生产的强制规定。

风险

如果没有适当的流程控制,单个受损的开发人员账户或恶意内部人员就可以绕过代码审查、安全扫描和审批流程,直接将代码推送到生产环境中。这可能导致部署后门、数据外泄代码或破坏性有效载荷。

漏洞代码示例

YAML (GitHub Actions) ❌ Bad
# No branch protection — anyone can push directly to main
name: Deploy
on:
  push:
    branches: [main]  # Triggers on any push to main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Deploys immediately — no approval gate!
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

安全代码示例

YAML (GitHub Actions) ✅ Good
name: Deploy
on:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production  # Requires manual approval
    steps:
    - uses: actions/checkout@v4
    - run: |
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

缓解措施清单

2️⃣ CICD-SEC-2 - 身份和访问管理不足

Critical

概述

CI/CD 系统涉及多个身份:人类用户、服务账户、机器人令牌和机器身份。不完善的 IAM 允许对资源库、管道和部署目标进行过度许可访问。共享凭证、过期账户和缺乏 MFA 会加剧风险。

风险

权限过高的 CI/CD 身份被破坏后,可以修改管道、访问机密、更改构建工件并部署到生产中。共享服务账户无法审计谁执行了操作。

漏洞代码示例

YAML (GitHub Actions) ❌ Bad
# Over-permissive workflow with admin token
name: CI
on: push
permissions: write-all  # Full permissions to everything!
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Using org-wide PAT with admin access
        curl -H "Authorization: token ${{ secrets.ADMIN_PAT }}" \
          https://api.github.com/repos/org/other-repo/contents/

安全代码示例

YAML (GitHub Actions) ✅ Good
name: CI
on: push
permissions:
  contents: read    # Minimum required permissions
  packages: write   # Only what's needed
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/create-github-app-token@v1  # Scoped app token
      id: app-token
      with:
        app-id: ${{ vars.APP_ID }}
        private-key: ${{ secrets.APP_PRIVATE_KEY }}
        repositories: other-repo  # Scoped to specific repo

缓解措施清单

3️⃣ CICD-SEC-3 - 依赖链滥用

Critical

概述

CI/CD 管道从外部软件包注册中心(npm、PyPI、Maven、Docker Hub)获取依赖关系。攻击者会通过依赖关系混乱、错别字抢注、维护者账户泄露和恶意软件包等方式利用这一点。一个中毒的依赖关系可在构建过程中执行任意代码。

风险

恶意依赖在安装过程中执行代码(安装后脚本、setup.py)、窃取机密、向构建工件注入后门或建立持久性。SolarWinds 和 Codecov 等供应链攻击证明了其灾难性影响。

漏洞代码示例

Jenkinsfile ❌ Bad
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // No lockfile verification, no integrity checks
        sh 'npm install'           // Fetches latest — could be compromised!
        sh 'pip install -r requirements.txt'  // No hash verification
      }
    }
  }
}

安全代码示例

Jenkinsfile ✅ Good
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // Use lockfile with integrity verification
        sh 'npm ci'                   // Uses package-lock.json
        sh 'npm audit --audit-level=high'
        // Python: verify hashes from lockfile
        sh 'pip install --require-hashes -r requirements.lock'
      }
    }
    stage('SCA Scan') {
      steps {
        // Software Composition Analysis
        sh 'trivy fs --scanners vuln,secret .'
      }
    }
  }
}

缓解措施清单

4️⃣ CICD-SEC-4 - 中毒管道执行(PPE)

Critical

概述

当攻击者可以修改 CI/CD 管道定义或注入在管道上下文中执行的恶意代码时,就会发生中毒管道执行(PPE)。这可能是通过操作分支中的管道配置文件、分叉中的拉取请求或修改共享管道模板发生的。

风险

可以修改管道配置的攻击者可以访问管道可用的所有机密、凭证和权限。他们可以外泄机密、篡改构建输出或部署恶意代码--所有这一切都在受信任的执行环境中进行。

漏洞代码示例

YAML (GitHub Actions) ❌ Bad
# Runs pipeline from fork PRs with access to secrets
name: CI
on:
  pull_request_target:  # Runs in base repo context with secrets!
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        ref: ${{ github.event.pull_request.head.sha }}  # Checks out fork code!
    - run: make build  # Fork's Makefile executes with secrets access
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}

安全代码示例

YAML (GitHub Actions) ✅ Good
# Separate workflows: untrusted build + trusted deploy
name: CI
on:
  pull_request:  # No secret access for PR builds
    branches: [main]
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4  # Checks out merge commit (safe)
    - run: npm ci && npm test   # No secrets needed for build/test
    - uses: actions/upload-artifact@v4
      with:
        name: build-output
        path: dist/

缓解措施清单

5️⃣ CICD-SEC-5 - 基于管道的访问控制(PBAC)不足

High

概述

基于管道的访问控制(PBAC)管理管道可以访问的资源:云账户、Kubernetes 集群、数据库和内部服务。PBAC 不足意味着管道的访问权限超出需要,违反了最小特权原则。

风险

权限过高的管道可被用来访问远远超出其预期范围的资源。一个次要服务的受损构建管道可被用于访问生产数据库、修改基础架构或转到其他环境。

漏洞代码示例

YAML (GitLab CI) ❌ Bad
# Pipeline with admin-level cloud credentials
deploy:
  stage: deploy
  script:
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY
    - aws configure set aws_secret_access_key $AWS_SECRET_KEY
    # This key has AdministratorAccess policy!
    - aws s3 sync dist/ s3://my-bucket/
    - aws ecs update-service --cluster prod --service myapp
    # Same credentials could access ANY AWS resource

安全代码示例

YAML (GitHub Actions) ✅ Good
name: Deploy
on:
  push:
    branches: [main]
permissions:
  id-token: write  # For OIDC
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: arn:aws:iam::123456:role/deploy-s3-only
        # Scoped role: only s3:PutObject on specific bucket
        aws-region: us-east-1
    - run: aws s3 sync dist/ s3://my-bucket/

缓解措施清单

6️⃣ CICD-SEC-6 - 证书卫生不足

Critical

概述

CI/CD 管道需要处理大量凭证:API 密钥、云令牌、注册表密码、SSH 密钥和签名证书。不良的凭据卫生状况包括在管道文件中硬编码秘密、在日志中打印秘密、使用未加密的秘密存储以及从不轮换凭据。

风险

CI/CD 认证泄露是最常见的初始访问载体之一。在构建日志中暴露、提交到版本库或未加密存储的机密,可让攻击者直接访问生产系统、云账户和工件注册表。

漏洞代码示例

Bash (CI Script) ❌ Bad
#!/bin/bash
# Secrets hardcoded and leaked in logs
export DOCKER_PASSWORD="MyS3cret!"         # Hardcoded!
echo "Logging in with $DOCKER_PASSWORD"  # Printed to logs!

docker login -u admin -p "$DOCKER_PASSWORD" registry.example.com
docker push registry.example.com/myapp:latest

# AWS credentials in environment — visible in process listing
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCY"
aws s3 cp artifact.zip s3://releases/

安全代码示例

YAML (GitHub Actions) ✅ Good
name: Publish
on:
  push:
    tags: ['v*']
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: docker/login-action@v3  # Handles credentials securely
      with:
        registry: registry.example.com
        username: ${{ secrets.DOCKER_USER }}   # Masked in logs
        password: ${{ secrets.DOCKER_TOKEN }}  # Short-lived token
    - run: |
        docker build -t registry.example.com/myapp:${{ github.ref_name }} .
        docker push registry.example.com/myapp:${{ github.ref_name }}

缓解措施清单

7️⃣ CICD-SEC-7 - 不安全的系统配置

High

概述

CI/CD 系统(Jenkins、GitLab、GitHub Actions runners)通常在不安全的默认配置下运行。这包括过时的软件版本、暴露的管理界面、禁用的安全功能、过于放任的网络访问以及跨项目共享的自托管运行程序。

风险

配置错误的 CI/CD 基础架构可能会被利用来获取未经授权的构建环境访问权限、拦截机密或转入内部网络。共享的自托管运行程序允许跨项目攻击,其中一个受损的工作流程会影响到其他工作流程。

漏洞代码示例

Groovy (Jenkins) ❌ Bad
// Jenkins with insecure configuration
// - Script console enabled without auth
// - Agent-to-controller access unrestricted
// - Outdated plugins with known CVEs

pipeline {
  agent any  // Runs on any available agent — no isolation
  stages {
    stage('Build') {
      steps {
        // Running as root on shared agent
        sh 'whoami'  // root
        sh 'docker build -t myapp .'
      }
    }
  }
}

安全代码示例

Groovy (Jenkins) ✅ Good
pipeline {
  agent {
    kubernetes {  // Ephemeral, isolated pod per build
      yaml """
        apiVersion: v1
        kind: Pod
        spec:
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
          containers:
          - name: builder
            image: builder:1.2.3
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
      """
    }
  }
  stages {
    stage('Build') {
      steps {
        container('builder') {
          sh 'make build'
        }
      }
    }
  }
}

缓解措施清单

8️⃣ CICD-SEC-8 - 不受监管地使用第三方服务

High

概述

CI/CD 管道通常会集成第三方服务:代码质量工具、安全扫描仪、通知系统和部署平台。这些集成会被授予访问令牌和权限,从而创建一个信任链。不受监管的使用意味着无法了解第三方服务可以访问什么或做什么。

风险

受到攻击的第三方服务(如 Codecov 漏洞)可以访问源代码、机密和构建工件。如果缺乏治理,团队可能会向未知服务授予过多权限,从而在供应链中形成隐形攻击载体。

漏洞代码示例

YAML (GitHub Actions) ❌ Bad
name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Unknown third-party action with full repo access
    - uses: random-org/code-analysis@main  # Unpinned, unvetted!
      with:
        token: ${{ secrets.GITHUB_TOKEN }}   # Full token access!
    # Uploading coverage to external service with repo token
    - run: |
        bash <(curl -s https://example.com/uploader.sh)  # Remote script!

安全代码示例

YAML (GitHub Actions) ✅ Good
name: CI
on: push
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Vetted action pinned to SHA
    - uses: github/codeql-action/analyze@8a470fddafa5cbc14  # Pinned SHA
    # Upload via official CLI tool, not remote scripts
    - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
      with:
        token: ${{ secrets.CODECOV_TOKEN }}  # Scoped token
        fail_ci_if_error: true

缓解措施清单

9️⃣ CICD-SEC-9 - 人工制品完整性验证不当

High

概述

构建工件(容器镜像、二进制文件、软件包)通过 CI/CD 管道流向生产。如果没有完整性验证,工件在任何时候都可能被篡改:在构建过程中、在传输过程中、在工件注册表中或在部署时。这会破坏从代码到生产的信任链。

风险

被篡改的工件可能包含后门、恶意软件或修改过的逻辑。如果没有签名和验证,就无法检测工件是否在构建后被修改过。攻击者可以替换注册表中的合法图像,或在传输过程中拦截工件。

漏洞代码示例

Bash ❌ Bad
#!/bin/bash
# Build and deploy without any integrity checks
docker build -t myregistry.com/app:latest .
docker push myregistry.com/app:latest

# On deployment side — no verification
docker pull myregistry.com/app:latest  # Could be tampered!
docker run myregistry.com/app:latest   # Tag is mutable!

安全代码示例

YAML (GitHub Actions) ✅ Good
name: Build and Sign
on:
  push:
    tags: ['v*']
permissions:
  id-token: write
  packages: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Build with immutable tag (SHA)
        docker build -t myregistry.com/app:${{ github.sha }} .
        docker push myregistry.com/app:${{ github.sha }}
    - uses: sigstore/cosign-installer@v3
    - run: |
        # Sign image with keyless signing (Sigstore)
        cosign sign myregistry.com/app:${{ github.sha }}
        # Generate and attach SBOM
        syft myregistry.com/app:${{ github.sha }} -o spdx-json > sbom.json
        cosign attest --predicate sbom.json myregistry.com/app:${{ github.sha }}

缓解措施清单

🔟 CICD-SEC-10 - 日志记录和可见性不足

Medium

概述

CI/CD 环境会产生关键的安全事件:管道执行、配置更改、秘密访问和部署活动。如果没有全面的日志记录和监控,管道中的恶意活动就不会被发现,事件响应也会受到严重影响。

风险

由于缺乏对 CI/CD 活动的可视性,攻击者可以在不触发任何警报的情况下修改管道、窃取机密和篡改工件。由于缺乏审计跟踪,因此无法确定漏洞的范围和影响。

漏洞代码示例

Bash ❌ Bad
#!/bin/bash
# Pipeline with no logging or audit trail
echo "Starting deployment..."
kubectl apply -f deploy.yaml
echo "Done."

# No record of: who triggered this, what changed,
# which image was deployed, what secrets were accessed
# Build logs expire after 30 days with no archival

安全代码示例

YAML (GitHub Actions) ✅ Good
name: Audited Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Log deployment metadata
      run: |
        echo "=== Deployment Audit Log ==="
        echo "Triggered by: ${{ github.actor }}"
        echo "Commit: ${{ github.sha }}"
        echo "Ref: ${{ github.ref }}"
        echo "Workflow: ${{ github.workflow }}"
        echo "Run ID: ${{ github.run_id }}"
    - name: Deploy with audit
      run: |
        kubectl apply -f deploy.yaml 2>&1 | tee deploy.log
        # Send audit event to SIEM
        curl -X POST "${{ secrets.SIEM_WEBHOOK }}" \
          -d '{"event":"deploy","actor":"${{ github.actor }}","sha":"${{ github.sha }}"}'

缓解措施清单

📊 汇总表

身份证 脆弱性 严重性 关键缓解措施
CICD-SEC-1流量控制机制不足Critical分支保护、所需审批、环境门
CICD-SEC-2身份和访问管理不足Critical最小权限令牌、OIDC、MFA、凭证轮换
CICD-SEC-3依赖链滥用Critical锁定文件、散列验证、私人登记册、SCA
CICD-SEC-4中毒管道执行(PPE)Critical单独构建/部署、不可变管道定义、分叉控制
CICD-SEC-5PBAC 不足HighOIDC 联合、范围化 IAM 角色、环境分离
CICD-SEC-6证书卫生不足Critical秘密管理、日志屏蔽、轮换、秘密扫描
CICD-SEC-7不安全的系统配置High短暂运行、非 root、插件更新、网络隔离
CICD-SEC-8不受监管地使用第三方服务High服务清单、SHA 引脚、无远程脚本
CICD-SEC-9人工制品完整性验证不当High共同签名、准入控制、SLSA 出处
CICD-SEC-10日志记录和可见性不足Medium审计日志、SIEM 集成、警报、日志保留