Your Website's Build Downloads Code From Strangers. In August, Some of It Turned Hostile.

On August 4 a self-spreading worm poisoned over 400 npm packages, the open-source building blocks that modern websites are assembled from. It ran the moment those packages were installed, before anyone started the site, and it went looking for the credentials that build machines hold. If your site has been rebuilt since early August, this is a fair question to put to whoever maintains it. There are four questions at the end of this post, and none of them require you to understand the code.
Nobody chose most of the code on your site
Modern websites are assembled rather than written from scratch. Whoever built your site picked a framework and a handful of libraries. The build then pulled in far more than that, because each of those pieces depends on other pieces, which depend on more pieces again. A single site build can involve hundreds of packages, and most of them are dependencies of dependencies that nobody on the project chose or read.
That is not sloppiness. It is how the web has been built for a decade, and the alternative, writing everything yourself, produces worse and less secure software. The tradeoff is that your site's ingredients list is long and mostly unread.
What happened on August 4
Attackers obtained a package maintainer's credentials. Microsoft Security reported that over 400 npm packages across multiple unrelated publishers were affected, spanning the keyv, flat-cache and cache-manager ecosystems, and stated that evidence points towards stolen maintainer credentials as the attack vector for initial compromise.
Socket named the affected packages: keyv, cacheable, cacheable-request, cache-manager, flat-cache and file-entry-cache, along with @thiennq/docs-viewer outside those namespaces. Those names will mean nothing to most business owners, and that is rather the point. Datadog Security Labs noted that some of these packages carry over 150 million weekly downloads. These are not hobby projects. They are the plumbing underneath things you did choose.
The install is the dangerous moment
This is the one technical idea worth carrying away, so here it is slowly.
When a package is installed, it is allowed to run scripts automatically. A preinstall hook is a script that runs as the package is being installed, before the application is ever started, before the site is built or deployed, before anyone looks at anything. It runs on the machine doing the installing.
The poisoned versions carried a malicious preinstall hook. It launched a file inside the package, which downloaded a standalone JavaScript runtime called Bun and executed a large obfuscated second stage. All of that happened during what looked like a routine install.
The window that matters is therefore the minute or two when a build machine is downloading packages, rather than anything that happens while visitors are on the site.
Why one stolen password became hundreds of packages
Most malware waits for somebody to make a mistake. This one recruited.
Datadog described the loop. The malware queries npm's token API and requires a matching token record with package-write permission and bypass_2fa set to true. Publishing tokens are what developers and automated systems use to release new versions of a package, and a token carrying that combination can publish without a second authentication step standing in the way.
Given such a token, it enumerates every package that identity can reach, downloads the latest release of each, inserts itself along with a loader, adds a preinstall hook, bumps the patch version and republishes. What appears in the registry looks like an ordinary bug-fix release.
Microsoft put the consequence in one sentence: one stolen token can produce malicious patch releases across every package available to that publisher. Only one maintainer had to be compromised for that to reach hundreds of packages, because each newly poisoned package carried the same token-hunting code into the next install.
It knew the difference between your laptop and your build server
The detail that should interest a business owner is that the malware behaved differently depending on where it landed.
On a developer's own workstation it detached itself and went quiet. Inside a build or deployment system it stayed active, specifically to reach workflow secrets. That is a deliberate choice about where the valuable material sits, and it is correct. A laptop mostly holds work in progress. A build machine holds the credentials required to put a website into the world.
Consider what has to be present for an automated deploy to function: keys to a cloud account, tokens that push code, credentials that reach a database. The machine that assembles your website necessarily holds the keys to your website, and a script running during the build runs with the same reach.
What it took
The harvest, as reported, covers most of the ways a modern site is deployed and run: npm tokens, GitHub credentials, AWS access keys, Kubernetes tokens and HashiCorp Vault credentials, with Socket also listing GCP and Azure keys and Kubernetes service account tokens. It read them from local files, from environment variables and from command line tools.
Socket also reported that it installed autostart hooks in editor and tool directories, so that it would start again on its own. Removing the offending package does not, by itself, remove the thing the package installed.
Where I stand, without overclaiming
I build static sites and deploy them myself, and I am not going to describe my own servers, paths or tooling in public, because publishing the shape of a live defence is its own risk.
A static site does have less running on the server than a database-driven CMS. No plugin runtime, no database answering queries on every page load, less software sitting there at runtime. That is a genuine advantage and it is not the advantage people think it is here, because the build still installs packages. Building is where this class of exposure lives, and it lives there for static sites and CMS sites alike.
The honest version of my own practice is narrower than a marketing page would put it. I keep credentials out of code repositories deliberately, and I scan for them automatically rather than trusting anyone to remember, which means a leaked key is less likely to be sitting in a file waiting to be read. That helps with one part of the problem. It does not help with the part where a build machine legitimately holds a deployment credential in memory while it deploys, because that credential has to exist for the deploy to work at all. This attack read environment variables. Anything the build can reach, something running inside the build can reach too.
No arrangement makes this impossible. What is available is a smaller blast radius, credentials scoped narrowly enough that one stolen key does not open everything, and knowing quickly enough to rotate them. I deploy the sites I look after, so when the question comes up I can say when a build ran and what went into it, which shortens the distance to an answer without guaranteeing the answer is a good one.
Four questions for whoever maintains your site
You do not need to audit anything yourself. You need to ask four questions and listen to how they are answered.
When did we last rebuild and deploy? This has a precise answer and it sets the exposure window. A site last built before early August was not installing packages during the period in question.
Do we use any of the affected package families? Send them the names from this post and ask them to check. This is their job, not yours, and it takes minutes. The answer you want is that they searched the full dependency tree, including dependencies of dependencies, rather than only the packages someone picked on purpose. "We do not use those" is only meaningful if they actually looked below the top level.
Where do our deployment credentials live, and what can they reach? The useful part of the answer is scope. A token that can deploy one site is a smaller problem than one that can reach every account you own. If the answer is vague, that vagueness is the finding.
If a credential leaked, how would we know? This is the question most likely to be met with silence. Detection is what turns a bad week into a bad quarter when it is missing.
Socket advised responders to remove the host-level dead-man's switch first, and only then rotate every credential reachable from the host, including npm tokens, GitHub access tokens and cloud provider keys. Rotating while the host is still compromised hands the fresh credentials straight to whoever is still sitting on it. This is work for whoever runs your site, not a task for an owner, but it is fair to ask whether they know the sequence.
The part worth remembering
Nothing here requires a business owner to learn what a dependency tree is. It requires knowing that your website is assembled from parts you did not choose, that the assembling is the moment those parts get to act, and that the machine doing the assembling holds your keys. Everything else is a conversation with the person you already pay.
The packages nobody chose are the ones nobody is watching.