BetterSWE DigestWhat is BetterSWE?

Deep Dive · Issue 19

How Two CI/CD Breaches Shared One Fatal Flaw

Codecov and CircleCI used different attack vectors, but both exploited the same assumption: every secret in a pipeline is available to every line of code running inside it.

A pipeline vault with keys to multiple systems, two attackers approaching

The Problem

Pipelines Hold Every Key

A pipeline vault with keys to multiple systems, two attackers approaching

A deploy job needs keys to source code, cloud infrastructure, container registries, signing services, and production environments. The pipeline is a credential warehouse by design, yet it receives a fraction of the security investment applied to the systems it deploys to.

Two breaches show how that concentration becomes a trap. Codecov (January to April 2021) and CircleCI (December 2022 to January 2023) used completely different attack vectors but exploited the same structural weakness: the pipeline's credentials are accessible to any code executing inside the build, and the platform holding them is itself under-hardened.

Two attack vectors, one target: the pipeline's concentrated credentials

Both incidents ended the same way: mass exfiltration of downstream customer secrets. The pipeline's trust boundary was too wide, and its detection surface too narrow.

Codecov

A Key Hidden in a Docker Layer

Docker image with exposed intermediate layer containing a key

The attacker pulled a GCP HMAC key from an intermediate layer in Codecov's public Docker image. The image was not squashed or multi-staged, so the key was retrievable by anyone who pulled it.

The Codecov attack chain, from Docker layer to mass exfiltration

Using that key, they modified the Bash Uploader script in GCS so the malicious version was served to every user. The script exfiltrated git remote origin URLs and all environment variables from each CI environment that ran it.

Why unsquashed Docker layers leak secrets

Docker images are built in layers. A multi-stage build copies only the final artifacts into the last layer, discarding intermediate ones. Codecov's image was not multi-staged, so the layer containing the GCP HMAC key remained in the published image. Anyone who pulled it could inspect every layer with docker history or docker save and extract the key from the intermediate filesystem.

The attack ran undetected for roughly two months, until a customer compared the SHA256 of the downloaded script against the published hash and found a discrepancy. Codecov had 29,000 enterprise customers; an estimated 15,000 files used the bash-uploader.

CircleCI

One Session Cookie, All Customer Secrets

Session cookie stolen from engineer's laptop used to access CircleCI platform

An engineer's laptop was compromised by malware that evaded antivirus. The attacker stole a 2FA-backed SSO session cookie and used it to impersonate the employee remotely, bypassing the second factor entirely.

The CircleCI attack chain, from laptop malware to plaintext secrets

The employee's role included generating production access tokens. The attacker accessed a subset of databases and stores and exfiltrated customer environment variables, tokens, and keys. All exfiltrated data was encrypted at rest, but the attacker extracted encryption keys from a running process, enabling plaintext access.

The breach ran from at least December 16, 2022 and was detected December 29 only when a customer flagged suspicious GitHub OAuth activity. CircleCI confirmed fewer than 5 customers reported unauthorized third-party access but urged all customers to rotate every secret ever stored on the platform.

The Trap

Five Places Secrets Leak

Five locations in a CI/CD pipeline where credentials can be exposed

Pipelines hold secrets in five locations, each with a different failure mode: secret stores, config files, runner memory, build logs, and caches. Any rotation plan covering only the secret store misses four of them.

Five locations where pipeline credentials persist and leak

Log masking does not help. Values sit in plaintext in process memory during execution, and the TeamPCP campaign scraped masked GitHub Actions values directly from memory, stealing 78,330 secrets from 2,186 organizations across GitHub, GitLab, Azure DevOps, and Jenkins.

No alarm separates reading a secret to deploy from reading a secret to steal.

Long-lived credentials compound the damage. 70% of secrets leaked in 2022 were still active in 2025, and 59% of compromised credential machines were CI/CD runners, not workstations. Stolen tokens generate API calls, not failed-login alerts. OIDC federation replaces static cloud keys with per-job, short-lived tokens, removing long-lived credentials from the pipeline entirely.

Wrap-Up

The Same Flaw, Two Doors In

Why it matters

Both breaches succeeded because the pipeline's trust model assumes all code running inside a job is authorized to read every secret the job holds. That assumption breaks when a dependency is poisoned, a platform is breached, or a session token is stolen. The structural fix is short-lived, per-job credentials that leave nothing to steal after the job ends, but most pipelines still run on long-lived keys stored in five places at once.

The short version

  • Codecov's attacker pulled a GCP key from an unsquashed Docker layer and poisoned a script that ran inside ~15,000 customer pipelines.
  • CircleCI's attacker stole a session cookie and generated production tokens, exfiltrating customer secrets for two weeks.
  • Pipelines hold secrets in 5 locations; rotating only the secret store misses 4 of them.
  • **59% of compromised credential machines in 2025 were CI/CD runners**, not developer laptops.
  • OIDC federation replaces long-lived cloud keys with per-job tokens, eliminating the static credential entirely.

Sources

  1. 1.5 CI/CD breaches analyzed: Why you need to update your software security | RL Blog
  2. 2.CI/CD Credential Exposure: What Attackers Steal From Pipelines and What to Rotate | CloudSEK
  3. 3.The Hidden Risks of Secrets Mismanagement in CI/CD Pipelines
  4. 4.Team PCP Stole 78,330 Secrets From 2,186 Organizations. CloudSEK Just Published the List. - StepSecurity
  5. 6.Post-Mortem / Root Cause Analysis (April 2021) - Codecov
  6. 7.CircleCI breach post-mortem: Attackers got in by stealing engineer's session cookie - Help Net Security
  7. 8.The Codecov Breach - Cycode
  8. 12.Enhancing CI/CD Pipeline Security with OIDC Tokens - Cycode