Supply chain attacks now target trust, not just dependencies

The next supply chain attack will not arrive as an obvious bad dependency. It will arrive through something your pipeline already trusts — a signed provenance attestation forged from a compromised build, a CI token scraped from runner memory, or a preinstall hook that looks identical to yesterday's clean version.

Engineering8 min read
CybersecuritySupply chainCI/CDDevSecOpsDependencies
Share

Over 454,000 new malicious packages were identified across npm, PyPI, Maven Central, and NuGet in 2025 alone — bringing the cumulative total past 1.2 million known supply chain malware artifacts. But the number hides the more important shift: modern supply chain attacks no longer rely on developers installing an obviously wrong package. They compromise the systems that teams already trust — build pipelines, OIDC tokens, provenance attestations, maintainer accounts — and publish malicious code through channels that look exactly like a normal release.

The threat model changed. Scanning dependencies for known vulnerabilities still matters, but it addresses the previous generation of attacks. The current generation forges the trust signals that scanning relies on. A package with valid SLSA Build Level 3 provenance, published from the official repository by the official maintainer's credentials, passing all CI checks — that package can still be malicious. The attack surface is no longer the dependency tree. It is the infrastructure that produces and certifies the dependency tree.

The supply chain is now the execution environment

Supply chain attacks have evolved from passive poisoning — publishing a typosquatted package and waiting for someone to install it — into active exploitation of build infrastructure. The self-replicating worms discovered in 2025 and 2026 move through CI/CD pipelines autonomously, stealing credentials and propagating into additional packages without human intervention.

The attack pattern: compromise a single maintainer account (often through credential reuse or phishing), inject a preinstall hook into a popular package, and use that hook to scrape secrets from the CI runner executing npm install. The stolen tokens — npm publishing tokens, GitHub Actions OIDC tokens, AWS credentials, Kubernetes service account tokens — become the means to compromise the next package, which compromises the next project, which exposes the next set of credentials.

This is not a theoretical chain. In May 2026, compromised visualization packages triggered cascading downstream impact into libraries with over a million weekly downloads. The payload scraped process memory from GitHub Actions runners, exfiltrated multi-platform credentials, and used stolen npm tokens to publish additional compromised packages — all within the legitimate CI/CD execution context.

Trust signals can be hijacked — including signed provenance

SLSA (Supply-chain Levels for Software Artifacts) was designed to solve exactly this problem: proving that a package was built from a specific commit, on a specific builder, without tampering. But provenance only proves origin. It does not prove that the origin was safe.

In May 2026, attackers exploited pull_request_target misconfigurations in GitHub Actions to hijack release pipelines and publish dozens of packages with valid SLSA Build Level 3 attestations. The provenance was genuine — the build ran on the expected platform, from the expected repository, signed by the expected identity. The pipeline itself was the compromised component. Every trust signal verified correctly because the attack operated within the boundaries of the trusted system.

This breaks the mental model most teams carry: "if the provenance checks pass, the artifact is safe." Provenance proves the artifact came from a specific pipeline. It does not prove the pipeline was not compromised before the artifact was produced. The verification answer is "yes, this was built here" — but the question teams actually need answered is "was this build environment trustworthy at the time it built this artifact?"

CI tokens are high-value production credentials

A GitHub Actions runner with contents: write and packages: write permissions can publish packages, push to repositories, and modify release artifacts. A runner with id-token: write can mint OIDC tokens accepted by cloud providers. These are not development conveniences. They are production credentials stored in the largest secret store most organizations maintain — the CI system itself.

The hardening priorities:

  • Principle of least privilege on workflow permissions. Default permissions: {} at the workflow level. Grant contents: read or id-token: write only to specific jobs that require them. Never use permissions: write-all outside of explicitly audited release workflows.
  • Pin actions to immutable commit SHAs, not tags. Tags can be force-pushed to point at different commits. A SHA is immutable. uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 survives tag manipulation; uses: actions/checkout@v4 does not.
  • Separate build and publish into distinct jobs. The job that compiles code does not need publishing credentials. The job that publishes should have read-only access to build outputs and write-only access to the registry — nothing else.
  • Use pull_request instead of pull_request_target unless the workflow explicitly needs access to secrets for fork-submitted PRs. The pull_request_target trigger runs in the context of the base branch with full secret access — one misconfigured workflow file turns every fork PR into a potential credential exfiltration vector.
  • Restrict OIDC token audience and claims. Scope OIDC tokens to the minimum set of cloud resources and conditions. A token that authenticates to * in AWS is not a temporary credential — it is a skeleton key with an expiration date.

Transitive dependencies turn exposure into a graph problem

Direct dependencies are auditable. Transitive dependencies — the packages your packages depend on — form a graph that no human reviews in full. A single compromised patch release five layers deep propagates into thousands of projects during the window between publication and detection.

The practical mitigations:

  • Lock dependencies to exact hashes, not version ranges. A package-lock.json or bun.lockb pinned to specific integrity hashes means a compromised patch release does not silently enter the build until someone explicitly updates the lockfile and reviews the diff.
  • Disable lifecycle scripts by default in CI. Use --ignore-scripts during installation. Allow-list only the specific packages whose postinstall hooks are required (native compilation, for instance). The vast majority of legitimate packages do not need to execute code during installation.
  • Monitor for dependency mutations. A patch release that changes no source code but adds a preinstall script is a signal. A release published from a different IP or geographic region than the maintainer's historical pattern is a signal. Tools that detect these anomalies at the registry level now exist — the question is whether teams integrate them before or after the incident.
  • Maintain an inventory of every package with transitive access to CI secrets. If a package runs during npm install in a job that has id-token: write permissions, that package has indirect access to the OIDC token. The effective blast radius is not the dependency tree — it is the intersection of the dependency tree and the permission graph.

The window between compromise and detection is the critical variable. In the May 2026 incidents, compromised patch releases were live for hours to days before registries pulled them. Every project that ran npm install during that window executed the payload. The projects using lockfiles pinned to the previous version were not affected — the compromised version never entered their build until a human reviewed the update. Lockfiles are not a performance optimization. They are a security boundary that converts a zero-day supply chain compromise into a reviewable diff.

What should teams lock down first against supply chain attacks?

The priority depends on the blast radius of a compromise. Start with the highest-value targets: publishing credentials and CI/CD token permissions.

What is the first step to harden CI/CD against supply chain compromise?

Audit every workflow file for excessive permissions. Default all workflows to permissions: {} and grant specific permissions only to jobs that need them. Remove pull_request_target triggers unless they are essential and have been reviewed by a security engineer. Pin all third-party actions to commit SHAs. This single pass eliminates the most common entry point for pipeline-level attacks without requiring new tooling.

Does SLSA provenance protect against supply chain attacks?

SLSA provenance proves that an artifact was built by a specific builder from a specific source. It does not prove the build environment was uncompromised at build time. Provenance is a necessary layer — it eliminates classes of tampering that happen after the build. But it is not sufficient when the attack occurs within the build pipeline itself. Treat provenance as one signal in a multi-layer verification stack, not as a binary trust decision.

Should teams block all packages without provenance attestations?

Blocking unattested packages is a defensible policy for production deployments — but the ecosystem is not there yet. The majority of npm and PyPI packages do not publish SLSA provenance. A practical intermediate step: require attestations for direct dependencies, monitor transitive dependencies for anomalies, and gate only the deployment pipeline (not every development install) on provenance verification.

The opposing view: package scanners are enough for most teams

A common argument holds that dependency scanning tools — Snyk, Socket, Dependabot, npm audit — catch the vast majority of supply chain threats before they reach production. For teams without dedicated security engineering capacity, investing in pipeline hardening and provenance verification is a distraction from higher-impact practices like enabling MFA on maintainer accounts, keeping dependencies up to date, and running basic vulnerability scans.

This view is correct about relative priority for small teams. A team with no scanning at all should add scanning before worrying about SLSA attestations. But the current generation of attacks specifically targets the gap between what scanners detect and what the build pipeline trusts. A compromised package published through a legitimate account, with no known CVE, and valid provenance — that package passes every scanner. The defensive posture that relies exclusively on scanning is the posture the current attacks are designed to evade.

Key takeaways

  • Modern supply chain attacks target trust systems — CI tokens, provenance attestations, maintainer accounts — not just dependencies.
  • Provenance proves origin. It does not prove safety. A package with valid SLSA attestations can still be malicious if the build pipeline was compromised.
  • CI runners with broad permissions are production credentials. Default all workflow permissions to empty and grant access per-job.
  • Pin actions to commit SHAs, disable lifecycle scripts in CI, and lock dependencies to exact hashes — these three controls eliminate the most common propagation vectors.
  • Transitive dependencies intersected with CI permission graphs define the real blast radius. Audit that intersection, not just the dependency tree.
  • Dependency scanners catch known threats. The current attack generation is designed to evade them by operating within trusted boundaries.

Conclusion

The supply chain threat model has shifted from "someone might install a bad package" to "someone might publish a bad package through a system the organization already trusts." The defenses that worked against typosquatting and known vulnerabilities — scanning, updating, basic hygiene — are necessary but no longer sufficient. The next layer requires treating CI/CD infrastructure as a security perimeter, treating every token as a potential lateral movement path, and accepting that provenance is a signal, not a guarantee. The attack that arrives through a signed, attested, CI-verified package from a maintainer account that was legitimate yesterday — that is the attack the current tooling does not catch by default, and the one every production team needs a response plan for.

Related articles

Command Palette

Search for a command to run...