I Ran npm install 1,000 Times This Year. Here's Why That Scares Me Now.

Written by spchash | Published 2026/03/25
Tech Story Tags: cybersecurity | npm | supply-chain-security | javascript | open-source | software-development | web-development | npm-trust-model

TLDRTL;DR: The GlassWorm campaign compromised 151+ GitHub repos and 72+ VS Code extensions in March 2026 using invisible Unicode payloads, AI-generated camouflage, and blockchain-based command infrastructure. As a solo developer running a Next.js app in production, I walked through what I checked, what I changed, and why indie builders can no longer ignore supply chain security.via the TL;DR App

Last week, while scrolling through security advisories, I stopped cold on a headline from Aikido Security. A threat actor called GlassWorm had compromised at least 151 GitHub repositories between March 3 and March 9. The attack had also spread to npm packages and VS Code extensions. And the payload was invisible. Not obfuscated. Not minified. Literally invisible to the human eye, hidden inside Unicode characters that render as blank space in every code editor on the planet.

I looked at my terminal. I had run npm install that morning without thinking twice. I do it constantly. We all do.

What Actually Happened

The GlassWorm campaign is not new. Aikido Security first discovered the technique in March 2025, when they found malicious npm packages hiding payloads inside Unicode Private Use Area characters. By October 2025, the actor had moved into the Open VSX extension registry and GitHub repositories. But the March 2026 wave is different in scale and sophistication.

The attack works like this: the malicious code uses Unicode variation selectors (ranges 0xFE00 through 0xFE0F and 0xE0100 through 0xE01EF) that produce zero visual output. Open a compromised file in VS Code, Vim, or any editor, and you see empty lines. Maybe some whitespace. Nothing suspicious. But JavaScript's interpreter reads those invisible bytes just fine. A small decoder passes them to eval(), and suddenly you are running a full malicious payload that steals tokens, credentials, and secrets.

What makes this iteration particularly nasty is the camouflage. Security researchers at Aikido suspect the attackers are using large language models to generate the surrounding code changes. The commits look like version bumps, documentation tweaks, small refactors. They are, as one researcher put it, "stylistically consistent with each target project." Manually creating 151 bespoke code changes across different codebases is not feasible for a human. Generating them with an LLM is trivial.

The command and control infrastructure runs on the Solana blockchain. The malware reads transaction memo fields to find its next instructions. You cannot take down blockchain transactions. You cannot modify them. The researchers at Koi Security, who first named GlassWorm, described it bluntly: "You're playing whack-a-mole with an opponent who has infinite moles."

And the latest evolution, reported by Socket on March 13, shows the actor abusing VS Code's extensionPack and extensionDependencies fields. A benign-looking extension gets installed, earns trust, then a later update quietly pulls in a separate GlassWorm loader as a dependency. Your editor installs the malware in the background. No prompt. No confirmation.

Why This Should Terrify Solo Developers

I build and maintain a Next.js application in production. My package-lock.json contains hundreds of dependencies. Each of those dependencies has its own dependencies. The tree goes deep, and I have never audited most of it. I doubt you have either.

This is the reality of modern web development. We stand on a tower of packages written by strangers, maintained by volunteers, and distributed through registries that have been targeted by supply chain attacks for years. We know this intellectually. We read the SolarWinds postmortem. We shook our heads at the event-stream incident. Then we opened our terminal and typed npm install again, because the alternative is not shipping anything.

But GlassWorm changes the calculation for me, and it should for you too. Previous supply chain attacks relied on typosquatting, dependency confusion, or compromising a maintainer's account. GlassWorm automates the entire pipeline. It steals developer credentials, uses them to push invisible payloads into legitimate repositories, then spreads itself further. It is a worm in the original sense of the word, and its propagation mechanism is our own trust in the packages we depend on.

Enterprise teams have security tooling, dedicated AppSec engineers, and SAST/DAST pipelines to catch this kind of thing. Solo developers and small teams have npm audit and good intentions. That gap has always existed, but the sophistication of attacks like GlassWorm is widening it fast. The dark side of open source is no longer a theoretical concern for indie builders. It is an operational risk that can compromise your users, your data, and your business overnight.

What I Actually Did After Reading the News

The honest answer is: I panicked for about ten minutes, then got practical. Here is what I did over the following 48 hours, and what I think any solo developer running a production app should consider doing.

I checked my lockfile against the known compromised packages. The Aikido and Socket reports include specific package names and repository URLs. I searched my package-lock.json for any overlap. I found none, but that is not the reassuring answer it sounds like. The 151 repositories identified are, by the researchers' own admission, a fraction of the total, since many had already been deleted before the research was published.

I ran a full dependency audit and actually read the output. Not just npm audit, which catches known CVEs but would miss a zero-day invisible payload. I also checked for packages with suspiciously recent ownership transfers, packages with sudden version bumps that included no meaningful changelog, and packages I had installed months ago and forgotten about. I removed two packages I no longer needed. Every dependency you do not use is attack surface you do not need.

I reviewed my CI/CD pipeline's exposure. My Vercel deployments run npm install on every push. If a compromised package made it into my lockfile, the build process would execute the payload in an environment that has access to my environment variables, API keys, and deployment tokens. I enabled stricter environment variable scoping and made sure secrets only exist in the environments that actually need them.

I pinned my dependency versions more aggressively. I was already using a lockfile, but I had several dependencies with loose version ranges in package.json. A compromised patch release could still slip through. I tightened those ranges and made a note to review changelogs before updating.

I started treating my VS Code extensions with the same suspicion I apply to npm packages. The GlassWorm campaign compromised at least 72 VS Code extensions that mimicked popular developer tools. I uninstalled extensions I was not actively using and checked the remaining ones against the indicators of compromise listed in the Socket report.

None of these steps are revolutionary. Security professionals will read this list and shrug. But that is precisely the problem. The fundamentals of securing your dependencies have been well documented for years, and most of us still do not follow them because the threat felt abstract. GlassWorm makes it concrete.

The Bigger Problem Nobody Wants to Talk About

The JavaScript ecosystem has a cultural problem with dependencies. We add packages for trivial tasks because the cost of adding a dependency feels close to zero: npm install, import, done. But every package is a trust decision, and we are making hundreds of those decisions without any due diligence.

The attack surface is not just the packages you install directly. It is every transitive dependency in the tree. A popular package with 10 million weekly downloads might depend on a utility maintained by a single developer who has not committed in two years. If that developer's npm token gets phished, the entire tree is compromised, and millions of projects inherit the payload on their next install.

GlassWorm exploits this reality systematically. It does not need to compromise a top-level package with vigilant maintainers and automated security scans. It targets the long tail: smaller repos, niche utilities, abandoned-but-still-installed extensions. The ones nobody is watching.

I do not think the solution is to stop using open source. That ship sailed a long time ago, and the ecosystem's benefits are real. But I do think we need to be more honest about the trade-offs. Every npm install is a bet that nobody in a chain of strangers has been compromised since the last time you checked. For most of us, "the last time we checked" was never.

What I Think Needs to Change

At the ecosystem level, npm and VS Code's extension marketplace need better provenance tooling. Supply chain attacks targeting developers are not a new category, and the fact that invisible Unicode payloads can still bypass both human review and automated scanning in 2026 is a failure of infrastructure, not just of individual developer hygiene.

At the individual level, and this is the uncomfortable part, we need to treat dependency management as a security practice, not a convenience feature. That means auditing regularly, removing what you do not use, questioning what you add, and accepting that shipping a little slower is better than shipping a compromised product.

I am not going to pretend I have solved this for my own projects. I still have hundreds of dependencies. I still run npm install without reading every line of every package I pull in. But after GlassWorm, I am at least thinking about what is inside those invisible lines of code. And that might be the most important change of all.


Written by spchash | Full-stack developer — Next.js, React, TypeScript, Node.js, Prisma, PostgreSQL, Vercel.
Published by HackerNoon on 2026/03/25