← Blog · 2026-09-08 · slopsquatting, supply-chain, packages

Slopsquatting explained: how hallucinated npm packages become malware

The attack in one paragraph

A language model is asked to parse a CLI flag. Confidently, it writes npm install fast-parse-utils-v3 — a package that does not exist. A developer accepts the diff. Sometimes the install fails and someone removes the line. Sometimes it doesn’t: because between the model inventing the name and the developer typing npm install, someone else registered it. That someone harvests hallucinated names from public model output, publishes a malicious package under each, and waits. The class has a name now — slopsquatting, or package hallucination.

The numbers, from the study that measured it

The measurement worth quoting is We Have a Package for You! A Comprehensive Analysis of Package Hallucinations in Code Generated by Large Language Models (Spracklen et al., USENIX Security 2025). It is the largest study of the phenomenon to date:

FindingFigure
Coding models tested16
Prompts per model~19,000
Average package hallucination rate19.6%
Commercial models~5%
Open-source models~21%
Unique non-existent package names generated205,474
Names regenerated on every repeat of the same prompt~45%
Names reappearing within 10 subsequent prompts~60%

The last two rows are the ones that turn a curiosity into an attack. A hallucination that happens once is a typo. A hallucination that reappears on roughly half of all identical prompts is a name an attacker can predict, register, and wait on — at scale, across a catalogue of 205,474 candidates.

Separately, Veracode’s 2025 GenAI Code Security Report (100+ models, Java, Python, C#, JavaScript) found that 45% of AI-generated code samples failed security tests, introducing OWASP Top 10 vulnerabilities — and that the security pass rate stayed flat across model generations, even as the code got better at being syntactically correct. Two different failure modes, same conclusion: correctness is not security, and newer models do not fix it.

Get started: add VibeShield to your PRs →

Why classic tools miss it

A dependency auditor asks: does this package have known vulnerabilities? A slopsquatted package has none — it was registered nine days ago and its first release is also its last. There is no CVE because the abuse is the existence. The signal lives somewhere else entirely:

SignalWhat “normal” looks likeWhat a squatted package looks like
Registry ageyearsdays — often days after the model’s answer
Maintainers2–50+1, newly-created account
READMEdocuments an APIabsent, or a copy-paste of the real package it sounds like
Install hooksnonepostinstall: curl … | sh
Name shapememorizable, humanmorphologically “generated”: adjective-verb-utils-v3

The last row matters more than people expect. Hallucinated names have a statistical shape — heavy on plausible-but-unusual token joins, light on memorized brand names — because they come from a distribution, not from memory. That shape is scorable.

What gates actually work

At generation time: nothing yet ships reliably; agents install what they propose. At commit time: a pre-commit hook that scores every dependency added to a manifest, offline, in about a second and a half. At PR time: a CI job that diffs the dependency tree, looks up registry signals for new nodes only, and comments the risky additions with the evidence — age, maintainers, install scripts, name score — before anything merges.

The rule of thumb we ship in the core pack: any dependency added by an AI-authored commit that is younger than 30 days, or has an install script, or scores as name-generated, needs a human to say its name out loud before it installs. That’s VS-PKG-001 and friends — the full rule list is in the docs.

Practical fixes, in order of value

  1. Gate the diff, not the repo. New dependencies are the attack surface; scanning the whole tree monthly catches yesterday’s news.
  2. Pin and vendor. A lockfile diff is a reviewable artifact. “The agent added 1 library and 200 packages” should be visible in the PR, which means using --no-save-style discipline or a lockfile check in CI.
  3. Never let an install-script run unreviewed in CI. npm ci --ignore-scripts by default; opt in per package with a reason.
  4. Treat typosquats and squats as the same bug class. Edit distance from a popular package is one more feature in the score.

VibeShield’s package-risk model does 1–2 and scores 3–4 at PR time — free and MIT-licensed, one YAML file to install.

Sources

Both are worth reading in full. Neither is affiliated with this project, and neither endorses it.