Last week, a self-propagating worm called CanisterWorm spread across npm by stealing tokens and publishing infected versions of legitimate packages — automatically. It started with the Trivy compromise on March 19th. Trivy. The security scanner most of us use to check for vulnerabilities. The irony writes itself.
Within days, CanisterWorm had infected 141 malicious package artifacts across 66 unique packages. The worm uses a smart contract on the Internet Computer blockchain as its command-and-control server — a first for npm malware. That means you can't just take down a domain to kill it. The C2 is decentralized and effectively permanent.
This isn't a "be careful what you install" story. This is an architecture story.
Your security scanner got owned
Here's what makes this different from the usual "malicious package found on npm" headline. The attack didn't start with a typosquatted package name or a sketchy new library. It started with Trivy — a tool with millions of downloads, used in CI/CD pipelines across the industry. 75 out of 76 trivy-action GitHub Action tags were force-pushed to malicious versions.
If your GitHub Actions workflow pins trivy-action@v4 instead of a specific commit SHA, you were vulnerable. That's not a hypothetical. That's how most people configure their actions.
I checked my own setup when the news broke. Two of my projects used trivy-action@v4. I got lucky — I hadn't run a pipeline during the attack window. But luck isn't architecture.

The npm install trust problem
Every time you run npm install, you're executing code from hundreds of strangers. We all know this. We all ignore it. The CanisterWorm mutation in @teale.io/eslint-config proved why that's reckless: it stole npm tokens from the developer's machine and used them to publish infected versions of their other packages. The worm spreads through the developers themselves.
Think about what that means for a solo dev. You install a package. It steals your npm token. It publishes malicious versions of your packages. Your users install the update. Now the worm is spreading through your supply chain. You didn't do anything wrong except trust the ecosystem defaults.
The fundamental architecture problem isn't "npm has malware." It's that most build pipelines treat package installation as a trusted operation. We pipe untrusted code through our CI with full network access, full filesystem access, and often access to deployment credentials.
What I'm changing
I spent the weekend rearchitecting my CI/CD setup. Here's the concrete stuff.
First, every GitHub Action is now pinned to a full commit SHA, not a tag. Tags are mutable — force-pushing a tag is exactly how the Trivy attack worked. SHA pinning is ugly but tamper-proof. I'm using Dependabot to get notified of updates, but I review each one manually now.
Second, I've added a read-only npm cache step that runs npm ci with --ignore-scripts in an isolated job before my main build. Post-install scripts are the primary vector for supply chain attacks, and most packages don't actually need them. The few that do get an explicit allowlist.
Third, I scoped my CI tokens. My npm publish token used to have full account access. Now it's scoped to specific packages with an IP allowlist. If CanisterWorm had grabbed my old token, it could have published malware under any of my packages. The new one can only touch the package I'm actively deploying.
None of this is complex. That's the frustrating part — these are basic architectural decisions that most of us skip because npm install has always "just worked."

The real cost
Every security-conscious architectural decision adds friction. Pinning SHAs means more maintenance. Disabling scripts means debugging when a legitimate package needs them. Scoping tokens means managing more credentials. For a solo dev shipping fast, this feels like overhead.
But CanisterWorm changed my math. The downside of getting compromised isn't just "my app breaks." It's "my npm token gets stolen and my packages infect my users." That's reputation-ending for a solo operation. The fifteen minutes I spend per week reviewing pinned dependency updates is cheap insurance.
If you're a solo builder running GitHub Actions with unpinned dependencies and full-access tokens, this week is the week to fix it. Not because you're paranoid. Because the worm that just hit npm was designed to spread through people exactly like us.
