It is a Tuesday morning. Your team's CI pipeline runs as normal. Tests pass. Build succeeds. Code ships to production. Nothing looks wrong.
But somewhere in that build, tucked inside a package your app has depended on for years, a tiny script quietly ran. It read your environment variables. It copied your cloud credentials. It sent them — over an encrypted connection — to a server in Eastern Europe.
You didn't get hacked. Your dependency did. And that's exactly the point.
In December 2020, the US Treasury, the Pentagon, and over 18,000 other organizations were breached in what became known as the SolarWinds attack. The attackers didn't brute-force any passwords. They didn't exploit a zero-day vulnerability. They simply slipped a backdoor into a legitimate software update — one that all of these organizations automatically downloaded and trusted because it came from a vendor they had been using for years.
Fast forward to early 2026. The same playbook, now running at internet speed.
The axios library — a tool used to make web requests, downloaded 100 million times every single week — was hijacked by a state-sponsored group. A remote access trojan (think: a hidden door into your computer that lets someone else walk in and look around) was quietly dropped onto every machine that ran npm install axios.
Around the same time, a popular VS Code extension called cline published version 2.3.0. Buried inside it was a silent instruction to install a second piece of software called openclaw — a credential harvester that hunted for passwords, API keys, and SSH keys on the developer's machine. No mention of this in the release notes.
And then there was Mini Shai-Hulud — a self-spreading worm (a program that copies itself from machine to machine automatically) that began bouncing between CI pipelines (the automated systems that build and deploy code). It hit TanStack, Mistral AI, UiPath, and others in a single wave, each one becoming the launchpad for the next infection.
None of these victims were careless. They were doing exactly what modern software development demands: building on open source, automating their pipelines, moving fast.
That is what makes supply chain attacks so insidious. And so important to understand — whether you write code for a living or you lead the people who do.
The One Idea That Explains Everything
Here is the core concept, in plain English:
Attackers don't target you directly. They compromise something you already trust — so that you deliver the attack to yourself.
This is not a new idea. It exists in every industry.
The 2008 melamine-in-milk scandal in China wasn't a problem with the brands on supermarket shelves. It was a problem at the bulk ingredient supplier, many steps upstream. Every brand that sourced from that supplier became a victim — and so did every consumer who bought from those brands. Nobody targeted them specifically. The supply chain did the work.
In software, your "supply chain" is every library, tool, and service your code depends on. And those dependencies have their own dependencies. And those have more. By the time you reach the bottom of that tree, you are implicitly trusting hundreds — sometimes thousands — of people and organizations you have never heard of.
How the Attack Actually Works

The diagram above maps the typical software supply chain: from the moment a developer writes code, through building and packaging it, storing it in a registry, distributing it as a dependency, integrating it into other projects, and finally running it in production.
Attackers look at this chain and ask a simple question: where is the easiest place to get in?
The answer is almost never "the final target." It is almost always somewhere in the middle — a trusted supplier, a shared tool, a package registry.
The attack pattern, once you see it, is everywhere:
Step 1 — Compromise. Find a weak link. Maybe a package maintainer left their npm login token in a public GitHub repository. Maybe an open source project hasn't had an active maintainer in two years and someone can simply request ownership. Maybe a CI system is configured to trust any code from a contributor without review. The barrier to entry is often astonishingly low.
Step 2 — Poison it. Add something malicious. Usually this hides in a postinstall script — a feature that lets packages run code automatically the moment you install them, with no confirmation prompt. The axios attack used this to drop a Remote Access Trojan. The cline attack used it to install a credential harvester. The code is typically obfuscated (deliberately scrambled to be hard to read) and the changes are buried in files most developers never look at.
Step 3 — Let the supply chain distribute it. Do nothing. The package registry, the CDN, the automated update system — all the infrastructure everyone already trusts — does the distribution for you. The package has a valid version number. It passes the usual checks. It downloads normally. Millions of npm install commands do the rest.
Step 4 — Impact thousands at once. One poisoned package. One upstream compromise. Thousands of victims who never made a single mistake. The attack scales automatically because the supply chain scales automatically.
The Six Places Attackers Actually Strike
Most security thinking focuses on your code. Supply chain attacks succeed because the real attack surface is much wider.
Your code and dependencies are the obvious starting point — open source packages, third-party libraries. But attackers also exploit typosquatting: publishing a package called crossenv knowing that some developers will mistype the real package name cross-env. Download it once and you've invited malware in.
Your build system and CI/CD pipeline (the automated system that compiles, tests, and deploys your code) is arguably the highest-value target. This is where OIDC tokens live — temporary credentials that grant the ability to publish packages. Steal one of these and you can publish a malicious version of a legitimate package as the legitimate author, with all the credibility that implies.
Package registries like npm and PyPI are where trust gets encoded. A package published without provenance attestation (a cryptographic record of exactly where and how it was built) is a package that could have come from anywhere.
Distribution channels — the update servers, mirrors, and download endpoints — are where one compromise becomes many victims. This is the SolarWinds mechanism: poison the distribution point and everyone downstream is automatically exposed.
Your deployment infrastructure — the cloud credentials, the configuration secrets, the IaC (Infrastructure as Code) templates that describe your entire cloud environment — is often where the real prize sits. Once an attacker is inside your CI pipeline, they can reach all of this.
Third-party services — the monitoring tools, the identity providers, the SaaS integrations — represent a sprawling surface area that most organizations have almost no visibility into. A compromised logging service could be reading everything that flows through it.
The Worm That Changed the Rules
The Mini Shai-Hulud attack deserves its own moment because it represents a genuinely new and alarming capability.
Traditional supply chain attacks require a human attacker to take action at each step: steal a token, publish a malicious package, wait for victims to install it. The attack spreads as far as that package's install base — then stops.

Mini Shai-Hulud automated the entire loop:
- The worm installs on a developer machine or CI runner
- It steals the OIDC token from the CI environment
- It uses that token to find all packages the victim has permission to publish
- It injects itself into those packages and publishes new malicious versions automatically
- Every developer who installs those packages becomes the next host — and their CI token becomes the next weapon
The worm spreads itself. Each new victim is automatically turned into an attacker.
What made this particularly alarming to security researchers: the worm produced packages with valid SLSA Build Level 3 provenance attestations. SLSA (Supply chain Levels for Software Artifacts) is the gold standard for supply chain integrity — it's a cryptographic proof that a package was built in a specific, verified way. It's supposed to be the highest level of assurance you can have.
The worm bypassed it. Completely. Because it had stolen legitimate credentials and used a legitimate pipeline to build the package. The attestation said "this package is authentic." It was right. It was authentically malicious.
This is the most important lesson in this entire article: a signature tells you where something came from. It doesn't tell you whether it's safe. Provenance verification and runtime behavioral monitoring are not substitutes for each other. You need both.
What Good Defense Actually Looks Like

The defense framework above is built around a simple idea: you cannot defend what you cannot see, and you cannot respond to what you cannot detect.
Here is how to think through each layer.
Know what you're running
The first step — and the one most organizations skip — is building a Software Bill of Materials (SBOM). Think of this as an ingredients list for your software: every library, every package, every tool your application depends on, including all the indirect dependencies (the dependencies of your dependencies, and so on, sometimes dozens of layers deep).
Without an SBOM, you are essentially running a kitchen without knowing what is in your pantry. You cannot check whether an ingredient has been recalled if you don't know it's there.
Tools like syft or GitHub's dependency graph can generate this automatically. It is not glamorous work, but it is the foundation of everything else.
Assess what is risky
Not all dependencies carry equal risk. A package maintained by one person, last updated three years ago, with 50 million weekly downloads, is a high-value target — attractive to attackers precisely because of its reach and low security maturity.
Look specifically for packages that publish via manual token rather than Trusted Publishing (where the publishing credential is generated automatically by the CI system and only valid for a single session, making stolen tokens much less useful). Every package in your dependency tree that publishes manually is a package where a stolen password immediately becomes your problem.
Harden your build
Three concrete changes that most teams haven't made:
Use npm ci instead of npm install in your CI pipeline. The difference: npm install can update packages if a newer version is available. npm ci installs exactly what is in your lockfile, nothing more, nothing less. It will fail loudly if anything doesn't match. This alone would have blocked several of the attacks described in this article.
Use --ignore-scripts when installing packages. This flag tells npm to skip postinstall scripts — the most common mechanism for hiding malicious code. Most packages don't need to run scripts on install. The ones that do can be explicitly whitelisted.
Pin your GitHub Actions to a full commit SHA. GitHub Actions (the automation steps in your CI pipeline) are themselves packages. A version tag like v3 can be silently changed by the action's author to point to different code. A commit SHA like abc123def456... is immutable — it will always refer to exactly the same code it referred to when you pinned it.
Deploy runtime detection
This is the most underused defense in the toolkit, and the most reliably effective.
StepSecurity's Harden-Runner is an open source GitHub Action that monitors all outbound network connections made by your CI pipeline during a run. It was the first system to detect the axios attack — by flagging an unexpected outbound connection to sfrclak.com seconds after npm install ran in CI. That one signal, in real time, was the earliest warning anyone had that something was wrong.
The principle is straightforward: if your CI pipeline is building code, it should be talking to known endpoints — your package registry, your artifact storage, your deployment target. It should not be calling home to a domain you have never seen before. A strict network egress policy (a list of allowed outbound destinations) combined with runtime monitoring turns invisible attacks into loud alerts.
Have a response plan before you need one
When — not if — something gets through, the difference between a minor incident and a major breach is often measured in minutes.
Know in advance:
- Who gets paged when an unexpected outbound connection is detected?
- How do you rotate all credentials in the affected environment?
- How do you pin downstream consumers to a safe package version?
- How do you communicate to users who may be affected?
Running through this for the first time during an active incident is the worst possible time to figure it out.
The Cross-Cutting Controls
Some defenses don't belong to any single step. They have to run everywhere, all the time.
Least privilege means every credential, every token, every permission should be scoped to the minimum required. Your CI job that runs tests does not need permission to publish packages. A developer's local npm account should not have admin rights on the organization. Every unnecessary permission is a potential pivot point.
MFA on everything that publishes. Multi-factor authentication on npm, PyPI, GitHub — any account that can push code or release a package. This is the single cheapest control relative to the attack surface it closes. The cline attack worked because a maintainer account was compromised. MFA would have been a significant barrier.
Secret scanning on every commit. Tools like GitHub's built-in secret scanner or truffleHog automatically flag credentials that appear in source code. A token committed even briefly — even to a private repository — must be treated as compromised and rotated immediately.
A dependency cooldown policy. The Mini Shai-Hulud worm published malicious versions and had them installed by CI pipelines within minutes, because those pipelines were configured to always use the latest version. A simple rule — don't automatically upgrade to a package version published in the last 24 hours — would have dramatically slowed the spread.
The Five Principles Worth Pinning Up

Assume breach. Not "this might happen someday." Assume it has already happened, or will happen soon, and build your detection and response accordingly. The organizations that fared best in the SolarWinds attack were not the ones who thought they were impenetrable — they were the ones who had strong detection, segmentation, and recovery capabilities.
Defence in depth. No single control is sufficient. SLSA was bypassed. Signatures can be faked. Package reviews miss obfuscated code. The teams that caught the Mini Shai-Hulud worm early were running multiple independent layers — lockfiles, runtime EDR, network egress controls, anomaly alerts. Each layer could be bypassed individually. Together, they created enough signal to catch the attack before significant damage occurred.
Least privilege is a habit, not a one-time setting. It has to be the default for every new token, every new integration, every new workflow. Start with zero permissions and add only what is explicitly needed.
Transparency beats obscurity. Share your SBOM. Publish your security posture. The open source packages that recovered fastest from supply chain incidents were the ones with clear ownership, active maintainers, and public security policies — because the community could identify and help remediate faster.
Evolve continuously. The threat landscape is moving faster than any fixed checklist can keep up with. Quarterly dependency audits, post-incident reviews, threat intelligence subscriptions — these are ongoing habits, not one-time projects.
What This Means for You
If you lead an engineering team or a technology organization, the honest message is this: your security posture is only as strong as the least-scrutinized package in your dependency tree.
That is not a criticism. It is the structural reality of how modern software is built. We stand on top of an enormous mountain of open source code, and that is mostly a wonderful thing — it lets small teams build things that would have required hundreds of engineers a decade ago.
But that mountain has cracks in it. And attackers have learned exactly where to look.
The good news: the gap between "doing nothing" and "meaningfully protected" is not as large as it feels. Three things, done well, would have caught or blocked most of the attacks described in this article:
- An SBOM — so you know what you are running
- Harden-Runner on every CI workflow — so you know what your pipelines are doing at runtime
- Lockfiles +
npm ci+--ignore-scripts— so an upstream change cannot silently slip into your build
Start there. Then work outward through the framework in Image 2.
The attackers are not waiting for you to be ready. But they are counting on you to keep trusting things you have never verified.
The incidents referenced in this article — SolarWinds (2020), axios npm hijack (2026), cline@2.3.0 (2026), Mini Shai-Hulud self-spreading worm (2026) — are all documented public cases. Detection of the axios and cline attacks is credited to StepSecurity's Harden-Runner. Research on the Mini Shai-Hulud worm is credited to StepSecurity and the broader npm security community.
Tags: Supply Chain Security · DevSecOps · npm · Open Source · Cybersecurity · Engineering Leadership