← OWASP Top 10 CI/CD Security Risks
CICD-SEC-4
Poisoned Pipeline Execution (PPE)
An attacker who can change what the pipeline runs (a workflow file, a script it calls, or input it interpolates) gets the pipeline's secrets and permissions. Pull requests from forks are the usual way.
Summary in ghtier's words. Read OWASP CI/CD's own text
Incidents (8)
Last 12 months (4): Megalodon: mass backdooring of CI workflows, Actions cache poisoning (Angular, TanStack), prt-scan: automated pull_request_target attacks, hackerbot-claw autonomous agent RCE
2026
- Megalodon: mass backdooring of CI workflowsOrganization May 2026
- Actions cache poisoning (Angular, TanStack)Organization May 2026
- prt-scan: automated pull_request_target attacksOrganization March 2026
- hackerbot-claw autonomous agent RCEOrganization February 2026
2025
- Nx "s1ngularity"Organization August 2025
2024
- Ultralytics build cache poisoningOrganization December 2024
2023
- Self-hosted runner takeovers (PyTorch and others)Organization January 2023
2021
- "Pwn requests": pull_request_target & workflow_runOrganization April 2021
Attack path techniques used
- Push directly, without review (Submit malicious code)
- Have a workflow approve the PR (Submit malicious code)
- Delete branches and workflow runs (Delete code or cover tracks)
- Add a workflow that dumps secrets (Steal CI secrets and tokens)
- Run PR code in a privileged workflow (Steal CI secrets and tokens)
- Read secrets from the runner (Steal CI secrets and tokens)
- Poison a shared Actions cache (Poison the build or published package)
- Trigger the publish workflow from a tampered branch (Poison the build or published package)
- Backdoor a persistent self-hosted runner (Poison the build or published package)
- Publish a malicious version with a stolen token (Poison the build or published package)
- Flip private repos to public (Read or expose private code)
- Leave a dormant workflow behind (Keep access)
Checklist items
The fixes for those techniques, plus the items ghtier tags with this risk.
- Branch protection on default/release branches: required reviews + required status checks
- Rulesets applied: push restriction, tag protection, sensitive file-path protection
- Set the default GITHUB_TOKEN permission to read-only at the org level
- Enable audit logging and export it to a SIEM for retention and detection
- CODEOWNERS in place, required on sensitive paths
- Inventory every Actions secret and its visibility/scope; the results are usually surprising
- Cloud credentials migrated from static keys to OIDC federation, scoped to repo + branch
- Audit every use of pull_request_target and remove or restructure risky ones
- Require approval for first-time/external contributor workflow runs on forks
- Third-party Actions pinned to a full commit SHA instead of a mutable tag or branch
- Restrict which Actions can run to GitHub-verified creators or an internal allow-list
- Adopt artifact attestations for build provenance on published binaries/images
- Disallow self-hosted runners on public repositories
- Publish packages with trusted publishing (OIDC) instead of long-lived registry tokens
- Put production secrets in environments with required reviewers
- Write and rehearse a credential-rotation runbook before you need it
- Restrict public repo creation, visibility changes, repo deletion, private forks and outside collaborator invites to owners
- Limit the number of organization owners to the minimum needed
- Set `persist-credentials: false` on actions/checkout wherever later steps do not push
- Do not restore Actions caches in release and publish workflows
Permissions involved
The GitHub permissions those incidents abused.