Defending Your Software Supply Chain: What Every Engineering Team Should Do Now

投稿日 4月 2日, 2026年

The software supply chain is under sustained attack. Not from a single threat actor or a single incident, but from an ecosystem-wide campaign that has been escalating for months and shows no signs of slowing down.

This week, axios, the HTTP client library downloaded 83 million times per week and present in roughly 80% of cloud environments, was compromised via a hijacked maintainer account. Two backdoored versions deployed platform-specific RATs attributed with high confidence to North Korea’s Lazarus Group. The malicious versions were live for approximately three hours. That was enough.

This follows the TeamPCP campaign in March, which weaponized Aqua Security’s Trivy vulnerability scanner, a security tool trusted by thousands of organizations, and cascaded the compromise into Checkmarx KICS, LiteLLM, Telnyx, and 141 npm packages via a self-propagating worm. Before that, the Shai-Hulud worm tore through the npm ecosystem in late 2025, and GlassWorm infected 400+ VS Code extensions, GitHub repos, and npm packages using invisible Unicode payloads.

The pattern is consistent across all of these incidents: attackers steal developer credentials, use them to poison trusted packages, and the compromised packages steal more credentials. It is self-reinforcing, it is accelerating, and it now has ransomware monetization pipelines behind it.

The common thread is implicit trust

If you look at what actually failed in each of these compromises, the answer is the same every time: trust was assumed where it should have been verified. Organizations trusted a container tag because it had a familiar name. They trusted a GitHub Action because it had a version number. They trusted a CI/CD secret because the workflow was authored by someone on the team. In every case, the attacker exploited the gap between assumed trust and verified trust.

The organizations that came through these incidents with minimal damage had already begun replacing implicit trust with explicit verification at every layer of their stack: verified base images instead of community pulls, pinned references instead of mutable tags, scoped and short-lived credentials instead of long-lived tokens, and sandboxed execution environments instead of wide-open CI runners. None of these are new ideas, and none of them are difficult to implement. What they require is a shift in default posture, from “trust unless there’s a reason not to” to “verify before you trust, and limit the blast radius when verification fails.”

Here is what we recommend every engineering organization should do, and what we practice ourselves at Docker:

Secure your foundations

Start with trusted base images

Don’t build on artifacts you can’t verify. Docker Hardened Images (DHI) are rebuilt from source by Docker with SLSA Build Level 3 attestations, signed SBOMs, and VEX metadata, free and open source under Apache 2.0. DHI was not affected by TeamPCP because its controlled build pipeline and built-in cooldown periods mean short-lived supply chain exploits (typically 1 to 6 hours) are eradicated before they ever enter the image. There is no reason not to use these today.

Pin everything by digest or commit SHA

Mutable tags are not a security boundary. This is exactly how TeamPCP hijacked 75 of 76 trivy-action version tags. Pin GitHub Actions to full 40-character commit SHAs. Pin container images by sha256 digest. Pin package dependencies to exact versions and remove ^ and ~ ranges. If a reference can be overwritten without changing its name, it will be.  Inventory every third-party GitHub Action in use across your org and enforce an allowlist policy as you cannot pin what you haven’t cataloged. Enable two-factor authentication on every package registry account in your organization like npm, PyPI, RubyGems, Docker Hub as account takeover of a single maintainer is how most of these attacks begin. Commit your lock files and use npm ci (or the equivalent in your package manager) in all CI pipelines – this prevents builds from silently pulling new versions that aren’t in your lock file.

Use cooldown periods for dependency updates

Both npm and Renovate support minimum release age settings that delay adoption of new versions. Most supply chain attacks have a shelf life of hours, and a 3-day cooldown eliminates the vast majority of them. We maintain a collection of safe default configurations for common package managers and tooling. Use it. Contribute to it.

Generate SBOMs at build time

When an incident hits, the first question is always: “are we affected?” If you use docker buildx to build your images, you can generate and attach SBOMs and provenance attestations during the build. Sign them. Store them alongside your images. When the next axios or Trivy happens, you check the build metadata rather than having to exec into live Kubernetes pods to figure out what’s running. Docker Scout can then continuously monitor those SBOMs against known vulnerabilities and policy violations.

Secure your CI/CD

Treat every CI runner as a potential breach point

TeamPCP’s credential stealer ran inside CI/CD pipelines, dumping process memory and sweeping 50+ filesystem paths for secrets. Anything accessible to a workflow step is accessible to an attacker who compromises a dependency in that step. Avoid pull_request_targe triggers in GitHub Actions unless absolutely necessary and with explicit security checks as this is the exact mechanism TeamPCP used to execute code in the context of the base repository with access to its secrets.  Audit what secrets each workflow step can reach. If a scanning step has access to your deployment credentials, that is a blast radius problem, not a scanning problem.

Use short-lived, narrowly scoped credentials

The root cause of the Trivy breach was a single Personal Access Token with broad scope used across 33+ workflows. Use short-lived, narrowly-scoped credentials. No single token should grant cross-repository or organization-wide access. Use a secrets manager, not environment variables scattered across workflow files. This is an area where the ecosystem, including Docker Hub, needs to continue improving, and we are actively working on it.

Use an internal mirror or artifact proxy

Place Artifactory, CodeArtifact, or Nexus between your build systems and public registries. Scan and approve versions before they reach your pipelines. Docker Business customers can also use Registry Access Management and Image Access Management to restrict which registries and images developers can pull, providing a lighter-weight policy layer for teams that don’t run a full artifact proxy.

Test dependency updates where production secrets don’t exist

Evaluate updates in dev/staging environments that have no access to production credentials. If a malicious package runs in staging, it steals nothing of value.

Secure your endpoints

This is where most of these attacks actually start. TeamPCP, Shai-Hulud, and now axios all deploy infostealers that sweep developer machines for credentials stored in dotfiles, environment variables, SSH keys, browser sessions, and cloud configs. Protecting CI/CD pipelines matters, but if the developer machine that authors those pipelines is compromised, the attacker inherits whatever that developer can reach.

Deploy canary tokens

Place fake credentials across your fleet, AWS keys, API tokens, SSH keys, that serve no purpose other than to alert you when they’re exfiltrated. If an infostealer sweeps a machine, canary tokens fire before the real credentials are used. Tools like Tracebit and Canarytokens make this trivial. If you have an MDM solution (Jamf, Intune, Jumpcloud), push canaries to every managed device. We deployed this across our fleet in under a day.

Clean up credential sprawl

Audit ~/.ssh/, ~/.aws/credentials, ~/.docker/config.json, .env files, and shell histories for hardcoded secrets. Move everything to a password manager or secrets vault (1Password, HashiCorp Vault). Passphrase-protect all SSH keys. An infostealer that lands on a machine with no cleartext credentials gets nothing useful. Audit the extensions and plugins installed across your developer tools (IDE extensions, browser extensions, coding agent extensions like skills, plugins, MCP servers, etc…) as these tend to run with developer-level permissions and most marketplaces do not re-review updates after initial publication.

Deploy EDR with behavioral detection

Endpoint detection and response tools should cover developer machines and CI runners, with detections tuned for credential sweeping, persistence mechanisms, and unusual process behavior rather than just known malware signatures.

Secure your AI development

AI coding agents are compounding supply chain risk in ways the industry is only beginning to appreciate. Agents install packages, modify configs, make API calls, and spin up containers with developer-level access. A compromised dependency pulled by an agent has the same blast radius as a compromised developer machine, and the people using these agents now include non-developers who may not recognize suspicious behavior.

Run agents in sandboxed environments

Docker Sandboxes (sbx) run AI coding agents like Claude Code, Gemini CLI, Codex, and others inside isolated microVMs. Each sandbox gets its own kernel, filesystem, Docker Engine, and network, completely separated from your host. Credentials are injected into HTTP headers by the host proxy and never enter the VM directly. Network access is deny-by-default, with explicit allowlists. If a compromised dependency runs inside a sandbox, it cannot reach your host filesystem, your Docker daemon, your other containers, or any domain you haven’t explicitly approved.

Govern your MCP servers

Model Context Protocol servers are the new unvetted dependency. They run with broad permissions, connect AI agents to internal systems, and 43% of analyzed MCP servers have command injection flaws. Use signed, hardened images for MCP servers. Docker maintains 300+ verified MCP server images with the same SLSA/SBOM standards as DHI. Docker’s MCP Gateway provides centralized proxy, policy enforcement, secret blocking, and audit logging for all agent-to-tool traffic.

Standardize on fewer tools, governed centrally

It’s tempting to run every AI tool and model. Don’t. Consolidate on a trusted stack, push managed configurations via MDM, and use Docker Desktop’s administrative features (registry access management, proxy configuration, image access management) to control what agents can pull and where they can push.

Build muscle for incident response

Maintain SBOMs for everything in production

When the next compromise drops, you need to answer “are we affected?” in minutes, not days. Build-time SBOMs via docker buildx, combined with Docker Scout’s continuous monitoring, give you that capability. If you have to exec into running containers to determine exposure, you’re already behind.

Have playbooks ready

Know how to freeze your GitHub org, pause CI/CD without breaking everything, revoke credentials in bulk, and communicate to customers before you need to do it under pressure. The time to figure out your incident response workflow is not during the incident. If you haven’t already, audit your npm/PyPI/Docker, Hub accounts for unauthorized publishes, review recent CI logs for unexpected network calls or secret access, and rotate any long-lived tokens that were accessible to CI in the past 90 days.

Verify before you trust, slow down where it counts

Most supply chain attacks burn out within hours. A small delay in adopting new versions, whether via cooldown periods, manual review gates, or simply waiting 72 hours, eliminates the majority of the risk. Speed of adoption is not worth the cost of compromise.

The landscape has changed, your defaults should too

The supply chain attack wave is not a single incident to respond to. It is a permanent shift in the threat landscape. The attackers range from nation-state operators like Lazarus Group to opportunistic teenagers like TeamPCP and LAPSUS$ who are building the plane as it takes off, using AI to accelerate, and monetizing through ransomware partnerships. The ecosystem they are exploiting, npm, PyPI, GitHub Actions, container registries, has not fundamentally changed in its trust model.

What has changed is that defenders now have the tools to establish explicit trust boundaries where implicit trust used to be the only option. Hardened base images, build-time attestations, sandboxed execution, and canary-based detection did not exist at this maturity level two years ago. The gap between organizations that adopt these layers and those that don’t is going to widen fast.

Everything we’ve recommended here, we practice at Docker. We pull from public registries, we run CI/CD pipelines, we use AI agents, and we face the same threat actors you do. This is how we’re protecting ourselves.

参考文献:

著者について

Docker 最高情報セキュリティ責任者

関連記事