This is a warning we have been wanting to put on the record. We are publishing it now because the wave we have been watching is large enough that we would rather have the note out before the next big one lands.
Most teams treat CI as a build system. CI is not a build system. CI is the highest-leverage production system the company runs. It has simultaneous write access to source code, deploy keys, secrets, package registries, and the machines of every downstream consumer. There is no other system in the modern stack with that combination of authority, and no other system that is defended this poorly.
We have been watching the attack class for about eighteen months. It is escalating. The year ahead is going to be a procession of incidents that look, after the fact, completely predictable.
What already happened
In April 2021, the Codecov bash uploader was compromised. The attacker modified the uploader script to exfiltrate environment variables from every CI run that piped curl into bash, which was most of them. The compromise lasted about two months before discovery. The blast radius was every secret in every workflow that uploaded coverage to Codecov, including private repositories at major vendors. Most affected teams could not, after the fact, enumerate which of their secrets had been exposed.
The shape before that was SolarWinds in December 2020. A different layer of the stack, the same shape of bug: trusted build output, no integrity check that traveled with the artifact, blast radius measured in customers rather than maintainers. The shape before that was event-stream in 2018, where a maintainer transfer delivered a wallet-stealing payload to every downstream that updated the dependency.
Three incidents, one pattern. That is the floor. The ceiling is what we expect to see in the months ahead.
What we expect next
Four patterns we have been watching, roughly in the order we expect them to land.
Worm-class compromises. A single maintainer takeover that spreads through that maintainer's other published packages, into the secrets used to publish them, and from those secrets to other maintainers' packages. Once one of these completes a self-replication cycle in a major ecosystem, the time between compromise and a meaningful percentage of the registry being affected is measured in hours. The npm registry's structure makes this particularly easy. We do not believe a worm of this class has been published yet. We believe one is in development. OIDC and trusted publishing abuse. Long-lived publishing tokens are clearly the wrong primitive. The ecosystems that haven't already moved off them are starting to, and the replacement most are converging on is workflow-bound OIDC. The improvement is real. It also concentrates trust in the CI workflow itself. Once an attacker has arbitrary code execution inside a workflow with publishing rights, they have publishing rights without ever touching a token. We have not seen this fully weaponized. The economics suggest someone will be working on it before the year is out. Cache poisoning as a primitive. The GitHub Actions cache is a per-repository key-value store reachable from any workflow that runs on a branch. Most teams treat cache contents as inputs to be trusted. They are not. A cache entry written by an untrusted workflow can be read by a trusted one. This has been a known issue for two years. It is still latent in approximately every CI configuration we audit. Hallucinated dependency names. Code-suggestion tools are entering the workflow at scale. The current generation will, with non-zero probability, suggest a package name that does not exist. Attackers will register the names. Developers will copy the suggestion into a dependency file. The attacker now has code execution in the developer's build, and by extension in the CI runner. We expect this class to grow with whatever the deployment curve of these tools turns out to be. We do not know the eventual base rate. We know the floor is greater than zero.Why this got worse
Three structural reasons.
CI used to do less. The set of things a typical pipeline did five years ago was test, lint, build, push artifact. The set of things a typical pipeline does today includes provisioning infrastructure, rotating production credentials, running database migrations, deploying mobile binaries, and publishing public packages. The blast radius of a compromise has grown roughly with the blast radius of what CI is now allowed to do.
CI is a soft target. The standard threat model for a build system was written when the build system had no production access. Most of the controls in place at most companies still match that model. The result is that the most consequential system in the stack is defended at the level of an internal Jenkins box from 2014.
The supply chain is opaque. A typical action pulls dependencies that pull dependencies that pull dependencies. Few teams pin to commit SHAs. Fewer audit the SHAs they pin to. Almost none re-audit when the pin moves. The Codecov incident was an existence proof. The lesson, broadly, has not been absorbed.
What we would be doing about it
If we were defending a non-trivial codebase right now, four changes would be on the short list.
Pin every action to a commit SHA, not a tag. Tags are mutable. SHAs aren't.
Treat every workflow that handles a secret as a production deployment. Code review. Approval. Logging. Restricted maintainer list. Separate identities for build secrets, deploy secrets, and publish secrets.
Use ephemeral runners. Self-hosted runners that persist between jobs are persistent footholds waiting to be claimed. Each job gets a fresh machine that dies when the job ends.
Treat your .github/workflows/ directory as the most security-sensitive part of the repository, because it is. Repository rulesets that require approval on workflow changes are free and almost nobody uses them.
None of this is novel. All of it is in the OpenSSF guidance, in CISA's advisories, in GitHub's own hardening documentation. Almost no team we have audited implements more than two of the four.
The honest one-liner
CI compromises are going to be the breach story of the next twelve months. We are putting this on the record now because the months ahead are going to be louder, and we would rather have called the pattern early than be one of the labs explaining it after the fact.
If you operate critical infrastructure and have not had this conversation internally yet, our suggestion is that you have it this week.