Your AI just imported a package that doesn't exist
LLM assistants keep inventing plausible package names. Unclaimed, those names are an attacker's opportunity — slopsquatting is typosquatting's AI-era cousin, and most teams have no check for it.
Webcuris Research
Security Engineering
·4 min read

The pull request looked fine. Clean diff, sensible tests, and at the top of the new file, three imports:
import { queue } from "async";
import { withRetry } from "smart-retry-utils";
import { backoff } from "exponential-backoff";Two of those packages exist. One of them — smart-retry-utils — does not. It never has. An AI coding assistant wrote it, a developer skimmed it, and it read so plausibly that it nearly shipped.
That near-miss is worth understanding, because the failure mode behind it is quietly becoming one of the more interesting supply-chain risks of the AI era.
Why language models invent packages
A language model completing code is doing exactly what it does with prose: producing the most plausible next tokens. Package names have strong internal grammar — exponential-backoff is real, so smart-retry-utils feels real. The model has seen thousands of names shaped like it. It is not lying; it is rhyming.
Researchers who studied this measured that a meaningful share of packages suggested by code assistants simply do not exist in any registry — and, more interestingly, that the same invented names recur across sessions and users. The models hallucinate consistently. That consistency is what turns a nuisance into an attack surface.
Slopsquatting: the attack hiding in the autocomplete
Typosquatting is old news: register lodahs and wait for someone to fat-finger lodash. Slopsquatting is its AI-era cousin, and it is better in every way that matters to an attacker:
- The victim doesn't make a mistake. Nobody mistypes anything. The name arrives in a diff, syntactically perfect, from a tool the team trusts.
- The names are predictable. Because models hallucinate the same names repeatedly, an attacker can harvest them — prompt an assistant across common tasks, collect the invented imports, and register the ones that recur.
- The payload runs at install time. A malicious package doesn't need anyone to call it. npm install scripts execute on the developer's machine, in CI, with CI's credentials.
Walk the timeline: an assistant suggests smart-retry-utils today and the build fails — annoying, visible, harmless. An attacker registers the name tomorrow with a working shim around a real retry library, plus an install script. Next month, the same assistant suggests the same name to someone else. This time the install succeeds. Nothing is visibly broken, which is the worst possible outcome.
The quieter sibling: phantom dependencies
There is a second, less dramatic version of the same disease. An import that works — but only by accident. The package exists, resolves today through hoisting or a transitive install, and is declared by nobody. Its version is pinned by nothing you control. It breaks when an unrelated dependency updates, and until then it sits invisible in every audit that reads package.json instead of reading the code.
AI assistants generate these constantly, because their training data is full of projects where the import happened to work. The model has no concept of your dependency tree.
What a real check looks like
The defense is unglamorous and completely mechanical, which is exactly what makes it automatable:
- Extract every import your code actually makes — from the source, not from the manifest. The manifest is the claim; the code is the truth.
- Diff against what is declared. Everything imported-but-undeclared is a finding, before any registry is consulted.
- Check undeclared names against the public registry. A name that is not there is either an invention or an internal package — and an unclaimed internal name is a dependency-confusion setup, which is its own emergency.
- Treat unclaimed names in generated code as blocking. Not a warning. The cost of being wrong is an attacker inside your install step.
Alongside that: install from lockfiles in CI (npm ci, never a bare install), consider --ignore-scripts where your stack tolerates it, and re-run the check continuously rather than once — the registry changes under you, which is the entire point of the attack.
The uncomfortable summary
AI assistants are writing a growing share of the world's code, and they introduce a category of dependency risk that no human workflow ever produced: imports that are wrong in a way that looks right, recurring predictably enough to be farmed. Code review was designed to catch human mistakes. This is not a human mistake.
Someone on your team should be reading your imports the way an attacker reads them: as a list of names, some of which are still unclaimed.
This check is built into [Webcuris](/) — every import in a connected repository, diffed against declarations and checked against the registry, on every scan. The [free tier](/pricing) runs the same engine as paid, and you can [scan one page free, no signup](/signup) to see the wider surface reading it does. This article is the write-up of why we built it.
Keep reading

Before you connect that MCP server, run these three commands
Connecting an AI assistant to a tool takes four seconds and grants a language model your permissions. Three commands, run first, tell you how the server authenticates and whether it follows the specification at all.

An assistant should be able to do less than you. Never more.
Everyone is connecting AI assistants to their tools by pasting an API key that never expires and isn't scoped to anything. Here is the authorization model we built instead, and the six decisions behind it.

What Is Slopsquatting? How AI-Invented Packages End Up in Real Codebases
Attackers register the package names AI assistants invent. What the research measured, how to find a hallucinated dependency already sitting in your repo, and why a one-time cleanup is not a control.
Everything this article describes is what Webcuris checks continuously — scan one page free, no signup.