Sonatype has documented an npm campaign it describes as a flooding dropper: 846 malicious packages, all carrying the same multi-stage JavaScript loader.
The number is the strategy. This is not a targeted attempt to compromise one popular library through a maintainer account. It is volume — hundreds of packages published on the assumption that some fraction will be installed by someone, somewhere, through a typo, a hallucinated dependency name, or an automated tool pulling something that looked plausible.
What the loader does
The chain is straightforward and competently built:
- Fingerprint the operating system. The loader identifies what it landed on before doing anything else.
- Fetch a platform-specific payload. Not one binary that tries to run everywhere — the right one for the host.
- On Windows, patch security functions. Interfering with the defensive machinery before proceeding.
- Establish persistence via a scheduled task. Ordinary, well-understood, and effective.
The OS-fingerprinting step is worth pausing on. It means the campaign expects to land on Windows, macOS and Linux — developer laptops, build agents and containers — and has prepared for each. That is not opportunistic. Someone budgeted for cross-platform work.
Why flooding works on package registries
Registries are optimised for publishing. That is the point: anyone can put a package up, immediately, at no cost. Every property that makes an open registry useful also makes flooding cheap.
Three things make the odds better than they sound:
Typosquatting still works because package names are typed by hand, and a name one character away from something popular gets installed regularly.
Dependency confusion persists because build systems can resolve an internal package name against a public registry if configured carelessly.
Model-hallucinated package names are a newer contributor. A coding assistant that confidently suggests a plausible-sounding library that does not exist creates a name an attacker can register — and the developer who was told to install it has no reason to doubt it.
That last route did not exist a few years ago and scales in exactly the direction a flooding campaign wants.
What defenders can actually do
Advice to "audit your dependencies" is not useful against 846 packages nobody has heard of. More specific:
- Pin and lock. A lockfile committed and enforced in CI means a new package cannot enter the build without someone deciding it should.
- Verify a package exists before installing it, particularly when an assistant suggested it. Check the registry page, the download counts, the repository, the publication date. A package published last week with no history is a decision, not a default.
- Deny by default on install scripts. Much of this class relies on execution at install time.
--ignore-scriptswith an allowlist is disruptive for a week and durable afterwards. - Watch for scheduled tasks appearing on developer machines and build agents. That is the persistence step here, and it is a detection most organisations already have the telemetry for.
- Treat build agents as production. They hold registry tokens, signing keys and deploy credentials. A dropper on a build agent is worth far more than one on a laptop.
The part that should worry maintainers
Registry defences are improving, and 846 packages did get identified. But the economics are unchanged: publishing is free and unlimited, detection is reactive, and the attacker only needs the fraction that gets installed before removal.
Every one of these campaigns is cheap to run and expensive to clean up — which is the same asymmetry that has kept the technique alive through every previous round of it.