AI Hallucinated a Package That Does Not Exist
A missing package is annoying. A package that exists only because an attacker registered the name your model invented is a supply chain compromise.
Your coding assistant wrote an import for a package that does not exist. That is the good outcome. Do not install anything under that name to make the error go away, because attackers watch for exactly these invented names and register them. Check the package against its registry and repository first, and if the name was hallucinated, replace the code rather than the dependency.
Why models invent package names
A language model predicts plausible text. Package names are extremely predictable text: a scope, a hyphen, a familiar noun. The model has seen thousands of real names with that shape, so producing a new one that looks right is trivial, and nothing in the generation step checks whether the name resolves to anything real.
Researchers at the University of Texas at San Antonio, Virginia Tech and the University of Oklahoma measured this properly. Their paper, We Have a Package for You, tested sixteen code-generating models across 576,000 generated code samples and found hallucinated dependencies in at least 5.2 percent of commercial model outputs and 21.7 percent of open-source model outputs, with 205,474 distinct invented package names recorded. The failures were not random noise either. They fell into recognisable shapes:
Conflations. Two real things fused into one plausible name, the way
express-mongoosesounds like something that ought to exist.Typo variants. A real package with a character out of place or a hyphen where a dot belongs.
Pure fabrications. A name that follows every convention of the ecosystem and has never existed.
This is a different failure from a model getting an API signature wrong. It is the same underlying behaviour as any other AI hallucination, but it fails in a direction that touches your dependency tree.
The part that makes it dangerous
Hallucinated names repeat. The same model asked the same kind of question tends to invent the same name, which turns a glitch into a predictable target. Security researchers named the resulting attack slopsquatting: rather than guessing typos of popular packages, an attacker runs code generation at scale, collects the invented names, and publishes real packages under them.
The proof of concept is well documented, and it came from a researcher rather than an attacker. Bar Lanyado of Lasso Security noticed models repeatedly recommending a Python package called huggingface-cli, which does not exist; the real tool installs under a different name. He registered an empty placeholder under the hallucinated name and, as his write-up records, it collected more than 30,000 genuine downloads in three months, with the invented install command turning up in at least one large company's public repository. Nobody was attacked. The next person to register one of those names may have other intentions.
What to do right now
Do not run the install command. That is the whole attack surface, and it usually executes install scripts before you have read a line of the code.
Search the official registry for the exact name and read the publish date, version count and download history. A package published three weeks ago with one version and no repository link is a red flag regardless of how it got into your file.
Open the linked source repository. No repository, or a repository with a single commit, means stop.
Ask what the code was actually trying to do. Nine times out of ten the real answer is one function in a package you already depend on, or fifteen lines you can write yourself.
Fix the code, then tell the assistant the package does not exist and ask for an implementation using only your current dependencies.
A thirty-second verification routine
Worth doing for any dependency an assistant adds, not only the ones that fail to resolve.
Signal | Where to look | Stop if |
|---|---|---|
Age | Registry publish date of the first version | Published in the last few months and unknown to you |
Adoption | Weekly download count | Very low downloads for a package presented as standard |
Source | Link to a public repository | Missing, empty, or a mirror with no history |
Maintainer | Other packages by the same publisher | No history, or a burst of similar packages published together |
Name shape | Compare with the ecosystem's real naming | Close but not identical to a package you know |
If you already installed it
Assume the package did something the moment it landed, because install lifecycle scripts run before you read anything. Work through this in order and do not skip the credential step because the code looked harmless.
Disconnect the machine from anything sensitive before you investigate further, and do the investigation in a container rather than on your laptop.
Rotate every credential that was readable from that environment: cloud keys, database passwords, tokens in your shell profile, anything in a dotfile. This is the step people skip and regret.
Read the package contents, especially install and postinstall scripts, and check for outbound network calls to anything you do not recognise.
Remove the package, delete the lockfile entry, and reinstall the tree from a clean state rather than editing around it.
Report the package to the registry. Every ecosystem has a report route, and a hallucinated name that has been squatted affects everyone whose assistant invents the same name.
If the environment held production credentials, treat it as an incident rather than a cleanup task, and follow the same sequence you would for any other tool that leaks your data: contain, rotate, then work out the blast radius.
Some ecosystems are riskier than others
The attack works everywhere with a public registry and no publication gate, which is to say almost everywhere. What varies is how much damage a bad install does before you notice.
Node and Python. Install-time script execution is normal, so a malicious package acts before you have read a line of it. These are the highest-risk ecosystems for this attack.
Rust and Go. No arbitrary install-time execution in the usual flow, so the code has to be built or run before it does anything. That is a meaningful delay, not immunity.
Internal registries with a proxy. If your organisation proxies public packages, an unknown name fails at the proxy rather than in your terminal, which is the single most effective control available.
Naming conventions matter too. Ecosystems with scoped or namespaced packages give an invented name fewer plausible shapes to occupy, which is why fabricated names in those registries tend to look slightly wrong to anyone paying attention.
Stopping it happening again
Verification catches the ones you look at. Process catches the rest.
Commit the lockfile and require it in CI. A pinned tree means new names cannot appear silently during a build.
Add a rule to your agent instructions. A line in your AGENTS.md file telling the assistant to use only dependencies already present in the manifest, and to say so explicitly when it wants a new one, removes most of the problem at the source.
Diff the manifest in review. Any change to the dependency list gets read by a person. This is a small addition to how you should already be reviewing AI-written code.
Install with scripts disabled during investigation. If you must pull something down to inspect it, do it in a throwaway container with lifecycle scripts turned off.
None of this is exotic. It is ordinary dependency hygiene, applied at the point where a machine started adding dependencies faster than a person reads them. Teams that already treat the wider category of AI coding tools as fast interns rather than oracles tend to have most of it in place already.
Frequently asked
Is a hallucinated package always malicious?
No. Most invented names resolve to nothing at all, which is why you see an error rather than a compromise. The risk is the narrow case where somebody has already registered the name, and you cannot tell those two situations apart from the error message.
Do open-source models do this more?
In the study above, considerably more: 21.7 percent of samples versus at least 5.2 percent for commercial models. That is a reason to verify more carefully when running a local model, not a reason to skip verification with a hosted one.
Will asking the model to double check help?
Only slightly, and not in a way you should rely on. The model has no live view of the registry unless it is given tool access to look, so a confident second opinion is still generated from the same guess. Check the registry yourself, or give the agent a tool that genuinely resolves the name.
What if the package exists but looks wrong?
Treat it exactly like a name that does not resolve. A recently published package with a familiar-sounding name, no repository and a handful of downloads is the shape of the attack, and debugging AI-generated code starts with removing it rather than working around it.
How did this land?
About the author

Developer Advocate
Steve builds something with Swarmz every week and writes up what worked, what broke, and what he'd do differently. Tutorials and hands-on guides are his lane.


