The most critical concentration risk in GitHub’s CI/CD ecosystem isn’t a single action - it’s a single organization. Docker controls six of the most commonly unpinned actions in the dataset, running inside the container build pipelines of thousands of the most popular open-source projects.
The Setup
When we mapped the supply chain crisis across GitHub’s top 50K repos, Docker’s official GitHub Actions stood out as a category of their own. Not because Docker actions are poorly built - they’re among the most professionally maintained in the ecosystem. The problem is concentration. One organization’s actions dominate the top of the unpinned actions list, creating a single point of failure that spans thousands of the most critical open-source projects.
This is a different kind of risk from the single-maintainer problem. Docker is a company with engineering teams and security practices. But organizational compromise is still possible - and the blast radius of a Docker GitHub org compromise would be unmatched in the CI/CD supply chain.
The Numbers
| Docker Action | Repos | Findings |
|---|---|---|
| docker/login-action@v3 | 1,848 | 5,099 |
| docker/setup-buildx-action@v3 | 1,845 | 4,258 |
| docker/setup-qemu-action@v3 | 1,181 | 2,038 |
| docker/build-push-action@v6 | 1,090 | 2,665 |
| docker/metadata-action@v5 | 900 | 1,734 |
| docker/login-action@v2 | 504 | 1,247 |
Docker’s total footprint: approximately 2,740+ unique repos affected across 130+ unique action references. These actions appear in more top repos than any other set of actions by any single maintainer or organization.
docker/login-action and docker/setup-buildx-action are nearly identical in adoption - 1,848 and 1,845 repos respectively. This makes sense: any repo building Docker containers needs both. They travel as a pair, which means a compromise of either action’s tag would likely hit the same 1,848 pipelines.
The pairing pattern extends across Docker’s action suite. A typical container build workflow uses three to five Docker actions in sequence: setup-qemu for multi-platform support, setup-buildx for the builder, login for registry authentication, metadata for image tagging, and build-push for the actual build and push. Each action is a link in the chain. Each link uses a mutable tag. The attack surface isn’t one action - it’s the entire pipeline orchestration layer that Docker provides.
What this means in practice: when we say 2,740+ unique repos are affected by Docker’s unpinned actions, that’s counting each repo once. Most of those repos use three to five Docker actions simultaneously, each unpinned. The finding count per repo is multiplicative - 1,848 repos with docker/login-action findings likely have 3-5 additional Docker action findings each.
Why Docker Actions Are the Chokepoint
Docker actions don’t just run arbitrary CI steps. They have privileged access by design.
docker/login-action authenticates with container registries - Docker Hub, AWS ECR, Google Container Registry, Azure Container Registry, GitHub Container Registry. During execution, this action holds your registry credentials in memory. A compromised version could exfiltrate those credentials and use them to push malicious container images to your registries.
docker/build-push-action builds container images and pushes them to registries. It has access to the build context (your application source code), the Dockerfile, and the push credentials. A compromised version could inject malicious layers into your container image - a backdoor in the base image, a modified entrypoint, an additional network call that phones home.
docker/setup-buildx-action configures the Docker BuildKit builder. It runs before the build step, setting up the environment that will process your Dockerfile. A compromised version could configure the build environment to intercept secrets, modify build output, or install persistent tooling on self-hosted runners.
docker/metadata-action generates tags and labels for container images. It determines what your images are tagged as - latest, version numbers, commit SHAs. A compromised version could manipulate image tags to cause deployments to pull the wrong image version.
The combination is the threat. These actions form a pipeline: authenticate → configure → build → push. Compromise any link and the attacker has access to everything that flows through it.
The Docker Pipeline Attack Scenario
Here’s how a Docker-focused chain attack would work:

-
Compromise docker/login-action. An attacker with push access moves the
@v3tag to a malicious commit. The modified action captures registry credentials during authentication and exfiltrates them. -
Silent propagation. On the next CI trigger in any of the 1,848 consuming repos, the compromised login action executes. Registry credentials for Docker Hub, AWS ECR, GCR, GHCR - whatever that repo authenticates against - are stolen.
-
Image poisoning. With stolen registry credentials, the attacker pushes backdoored container images to the repo’s container registry. The images use the same tags (including
latest) as the legitimate ones. -
Deployment propagation. Every system pulling that container image - Kubernetes clusters, cloud deployments, local development environments - now runs the attacker’s code. The blast radius extends from CI/CD into production.
This is a supply chain attack that jumps domains - from the CI/CD pipeline supply chain into the container image supply chain, and from there into production infrastructure. The Docker chokepoint is the bridge between these two supply chains.
What makes this scenario particularly dangerous is the detection gap. Traditional container scanning tools (Trivy, Snyk Container, Anchore) scan the resulting image for known CVEs in installed packages. They don’t detect a malicious layer injected during the build process - because the injected code isn’t a known vulnerability. It’s novel malware placed by the build tool itself. The container scanner sees a clean base image with expected packages. The backdoor lives in a layer that the scanner doesn’t flag because it was added by the “trusted” build process.
Similarly, CI/CD logs would look normal. The workflow file hasn’t changed. The action reference still says @v3. The build output still produces an image. Everything appears to work exactly as expected - because the compromise is upstream in the action code, not in the workflow configuration.
In my red team experience, these cross-domain attacks - where the compromise crosses from one supply chain into another - are the hardest to detect and the most impactful. The defenders looking at CI/CD don’t see the container issue. The defenders looking at containers don’t see the CI/CD issue. The attack lives in the gap between teams.
Version Sprawl in Docker Actions
Docker actions don’t just have one mutable tag - they have 28.
docker/build-push-action has been referenced across 28 unique mutable refs in our dataset:
| Version Range | Notable Versions | Status |
|---|---|---|
| v1-v3 | @v1, @v2, @v3 | End-of-life - still in active use |
| v4-v5 | @v4 (128 repos), @v5 (291 repos) | Previous majors - widely used |
| v6 | @v6 (610 repos) | Current - most common |
| Patch | @v6.19.2, @v5.x.x | Specific patches - still mutable |
| Branch | @master (3 repos) | Worst case - tracks every commit |
85+ repos still use v1 through v3 of Docker actions - end-of-life versions that are no longer maintained but still resolve to code when referenced. An attacker who compromises an EOL tag faces even less scrutiny because nobody is watching those old versions.
The 3 repos pinned to @master are the most exposed - every commit to Docker’s action repos executes immediately in those pipelines. But even @v6.19.2, which looks specific, is a mutable Git tag. It can be moved just as easily as @v3.
The Downstream Impact
The repos using Docker actions unpinned aren’t hobby projects. They’re the infrastructure of the software industry.
Cross-referencing our Docker action findings with the broader dataset, the repos that depend on Docker’s unpinned actions include major cloud provider repos, OSS foundation projects, AI/ML frameworks, distributed databases, and developer tools used by millions. When we say 1,848 repos use docker/login-action@v3, those repos have a combined downstream fork count in the tens of millions.
The concentration creates a cascade effect specific to Docker’s position in the ecosystem. Docker actions are uniquely positioned at the intersection of two supply chains: the CI/CD pipeline supply chain (GitHub Actions) and the container image supply chain (Docker Hub, registries). A compromise at this intersection doesn’t just affect CI - it poisons the container images that flow into production deployments worldwide.
Consider the downstream path: a compromised docker/build-push-action injects a malicious layer into a container image during the build. That image gets pushed to a registry. Kubernetes clusters, cloud deployments, and development environments pull the image. The malicious layer executes in every context that runs the container. The CI/CD compromise has crossed the boundary into runtime - and the repos that built those images have no idea, because their workflow files haven’t changed.
This is what makes the Docker chokepoint different from other concentration risks. It’s not just about code running in CI - it’s about code flowing into every deployment that consumes the build output.
Who Depends on Docker Actions
The language communities most exposed to the Docker chokepoint map predictably to container-heavy ecosystems:
- Go repos heavily use Docker actions for multi-platform binary builds and container packaging
- Rust repos pair Docker actions with dtolnay/rust-toolchain for cross-compilation into container images
- TypeScript/Node repos use Docker for production container builds alongside npm-based CI
The overlap with the language risk matrix data is notable: the languages with the highest CI/CD vulnerability rates (Rust at 77.9%, TypeScript at 61.7%, Go at 53.8%) are also among the heaviest Docker action consumers. Complex build toolchains drive both higher Docker action adoption and higher overall vulnerability rates.
The Single-Maintainer Contrast
Docker is an organization - which makes its concentration risk different from the single-maintainer problem. The risk profile is lower on the credential compromise axis (corporate accounts have MFA, SSO, audit logs) but higher on the blast radius axis (one org, six actions, 2,740+ repos).
The comparison:
| Maintainer | Type | Repos | Actions | Compromise Vector |
|---|---|---|---|---|
| docker | Organization | 2,740+ | 6 | Org compromise, insider, CI/CD of the action itself |
| action-gh-release | Individual | 1,405 | 1 | Personal credential compromise |
| setup-php | Individual | 1,147 | 1 | Personal credential compromise |
| rust-toolchain | Individual | 989 | 1 | Personal credential compromise |
Docker’s risk is concentration. action-gh-release’s risk is fragility. Both are supply chain problems, but they require different mitigations. Docker actions should be SHA-pinned because of their blast radius. Single-maintainer actions should be SHA-pinned because of their fragility. In both cases, the fix is the same - but the urgency comes from different threat models.
The Codecov Parallel
The Docker chokepoint isn’t unprecedented - it mirrors the Codecov incident of April 2021. Codecov’s Bash Uploader script was modified by an attacker who gained access through a compromised Docker image in Codecov’s CI pipeline. The modified script exfiltrated environment variables - including CI secrets, tokens, and keys - from every repo running the uploader.
The parallel is instructive: Codecov was a single tool in widespread use across thousands of repos. The compromise was silent - the uploader still functioned correctly. The attack ran for over two months before detection. And the blast radius was massive, with companies like Twitch, HashiCorp, and others disclosing potential impact.
Docker’s actions occupy an even more central position than Codecov’s uploader did. codecov/codecov-action appears in 1,049 repos in our dataset across 35 version refs. Docker’s login-action alone is in 1,848 - nearly double - and Docker controls five additional actions in the same pipeline. The lesson from Codecov is that these concentration risks aren’t theoretical. They’ve been exploited before. The question is whether Docker’s chokepoint gets exploited before the ecosystem pins its way out of the blast radius.
What SHA-Pinned Docker Actions Look Like
The difference between vulnerable and secure Docker action usage:
Before (mutable - vulnerable):
- uses: docker/login-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
After (SHA-pinned - secure):
- uses: docker/login-action@74a8a23... # v3.4.0
- uses: docker/setup-buildx-action@b5ca514... # v3.10.0
- uses: docker/build-push-action@14487ce... # v6.14.0
The SHA pin locks the reference to a specific commit. The version comment preserves readability. If Docker pushes a new version, your workflow keeps running the code you reviewed. You upgrade when you choose to, not when the tag moves.
Runner Guard’s autofix engine performs this transformation automatically - resolving every mutable Docker action reference to its current SHA with a version comment. The Fix It guide covers the complete process.
What You Can Do About It
-
SHA-pin all Docker actions immediately. docker/login-action, docker/setup-buildx-action, docker/build-push-action, docker/metadata-action, docker/setup-qemu-action. These are the highest-blast-radius actions in the ecosystem. Pin them first.
-
Configure Dependabot for Docker action updates. SHA pins need maintenance - when Docker releases security patches, you need to update your pins. Dependabot automates this with PR-based updates.
-
Audit your Docker action versions. If you’re using v1-v3 of any Docker action, you’re on an end-of-life version. Update to current and SHA-pin in a single step.
-
Consider Docker’s container signing. Docker Content Trust and Sigstore provide image-level verification that complements action-level SHA pinning. Pin the action AND verify the image.
-
Monitor Docker’s GitHub organization. If Docker’s org security posture changes - ownership changes, unusual access patterns, public incidents - that’s a signal to re-evaluate your dependency. Continuous monitoring catches these signals automatically.
The Docker chokepoint illustrates why supply chain security can’t focus on individual actions in isolation. It’s the concentration pattern - one org controlling the build pipeline infrastructure for thousands of projects - that creates systemic risk. The fix is mechanical: SHA-pin, configure updates, monitor. The risk is structural: a single point of failure at the foundation of the container ecosystem.
The broader lesson extends beyond Docker. Any organization whose actions dominate a critical pipeline function - build, deploy, sign, publish - creates a chokepoint. Docker is the current example. As the ecosystem evolves, new chokepoints will emerge around whatever tooling developers converge on next. The defense isn’t just pinning Docker actions today - it’s building the muscle to identify and pin whatever becomes the next concentration risk tomorrow. That requires continuous monitoring of your CI/CD dependency landscape, not just periodic audits.
Related Articles
Scan your repos today. Runner Guard is Vigilant’s free, open-source CI/CD security scanner - the same tool that powered this research. Install it in under a minute:
brew install Vigilant-LLC/tap/runner-guard
runner-guard scan github.com/owner/repo
14 security rules. Zero configuration. One command.
The detection capabilities described above are active across Vigilant client environments today. If your organization wants to assess its current exposure to this attack chain — or understand how our managed services align to your specific environment — contact your Vigilant account team or reach us at vigilantdefense.com.
This event reinforces what Vigilant has long asserted:
Nation-state adversaries are not probing our networks — they are preparing battlefields.
Stay alert, stay aggressive, stay Vigilant,
Chris Nyhuis
CEO, Vigilant
Vigilant, 7570 Bales Street
Suite 250, West Chester
Ohio 45069, United States
855-238-4445
Background
CEO of Vigilant, a global cybersecurity firm he has led for 16 years. 30+ years of experience across offensive security, SCADA/IoT, and critical infrastructure defense. Holds multiple patents including Forensically Validated Detection Systems and Secure Protocol Translation. Former instructor at a US intelligence school. Certified human trafficking investigator and OSINT practitioner. Vigilant dedicates 25% of profits to combating human trafficking, child exploitation, and supporting orphan care worldwide.