Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
Academy CI/CD Pipeline Security
Advanced · 25 min

CI/CD Pipeline Security

Understand how secrets leak in CI logs, malicious PR attacks, and why OIDC tokens replace long-lived credentials.

1 CI/CD Attack Vectors

CI/CD pipelines have elevated privileges for deployment. Compromising a pipeline can mean full control of production infrastructure.

Secrets in CI logs:

# Vulnerable GitHub Action
- name: Deploy
  run: |
    echo "API Key: $API_KEY"  # Logged to CI output!
    curl -H "Authorization: $DB_PASSWORD" https://api.example.com
    # Passwords in error messages also appear in logs

Malicious PR execution (poisoned pipeline execution - PPE):

# Vulnerable workflow triggered on pull_request from forks
on:
  pull_request:
    # No restriction — anyone can trigger this!
    
steps:
  - uses: actions/checkout@v3
  - run: npm test  # Runs code from the PR — ATTACKER CONTROLS THIS!
  - run: deploy.sh ${{ secrets.PROD_TOKEN }}  # Secret accessible to PR code!

Long-lived credentials: Static IAM keys stored as CI secrets can be exfiltrated and used indefinitely after a CI compromise.

2 Secret Masking, OIDC, and PR Restrictions

Secure CI/CD with OIDC short-lived tokens, secret masking, and restrictions on pull request workflows.

OIDC instead of long-lived credentials (GitHub Actions + AWS):

permissions:
  id-token: write
  contents: read

steps:
  - name: Configure AWS credentials via OIDC
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789:role/github-actions-role
      aws-region: us-east-1
  # No static AWS keys! Short-lived token created per workflow run

Restrict PR access to secrets:

on:
  pull_request:
    # Default: no access to secrets from forks
    # Use pull_request_target only with extreme care!

  push:
    branches: [main]  # Full secrets only on main branch pushes

Defense checklist:

  • Use OIDC/workload identity instead of static cloud credentials
  • Never echo secrets in CI steps — secret masking is a fallback, not primary defense
  • Do not grant fork PRs access to secrets
  • Pin GitHub Action versions to SHAs, not tags
  • Limit GITHUB_TOKEN permissions to minimum required
  • Use separate service accounts per pipeline with minimal IAM

Knowledge Check

0/3 correct
Q1

What is a "poisoned pipeline execution" (PPE) attack?

Q2

What is the security advantage of OIDC tokens over static IAM credentials in CI/CD?

Q3

Why should GitHub Action version tags (like uses: actions/checkout@v3) be replaced with SHA hashes?

Code Exercise

Restrict PR Workflow Secrets Access

The workflow runs tests on pull requests including from forks, with access to deployment secrets. Separate the test job (safe for PRs) from the deploy job (main branch only with secrets).

yaml