Ask a model for a Python PDF table extractor and it may tell you to pip install tabula. That package exists. It resolves right now, version 1.0.5, and it is an ASCII table formatter by an author with no connection to PDF extraction whatsoever. Its last release was in November 2012.
The one you wanted is tabula-py.
I checked four names this afternoon, on 2 September 2026. They come from a paper published on 24 August, as examples of package names models invent. Every single one returns HTTP 200 from PyPI.
| The model says | PyPI answer | Last release | What you actually wanted |
|---|---|---|---|
pip install pil | 200, v1.1.6 | 6 releases, long dormant | pillow, last release 1 July 2026 |
pip install faiss | 200, v1.5.3 | 16 April 2019, one release | faiss-cpu, last release 3 Aug 2026 |
pip install tabula | 200, v1.0.5 | 1 November 2012 | tabula-py |
pip install haystack | 200, v0.42 | 3 July 2017 | haystack-ai, v3.1.0 on 24 August 2026 |
haystack on PyPI is a tool for searching C structures in process memory. The haystack your agent means is a framework for building LLM applications. They share a name and nothing else.
So here is the problem with the advice everyone gives.
The check everyone recommends misses half the attack
Slopsquatting is the attack where a model invents a package name consistently enough that somebody can register it first and wait. The defence in every write-up, including the sensible ones, comes down to the same instruction: before you install what the agent suggested, check that the package is real.
That advice has a specific mechanical meaning. Ask the registry. If you get a 404, the model made it up. If you get a 200, the name is fine.
The 24 August paper puts the flaw in one sentence:
An attacker who has already registered the hallucinated name trivially bypasses a pure 404 check.
Its authors, Akash Raj and Sargam Sahu, built a two-layer detector precisely because one layer is not enough. Their first finding is the one that should end the existence check as a defence: half of the hallucinations their pipeline flagged were packages already registered on PyPI, sitting there as low-quality lookalikes of well-known projects. The deterministic layer missed all of them. A classifier trained on name and metadata caught them.
pil, faiss, tabula and haystack are their examples. That table above is what a 404 check tells you about all four: nothing.
The check fails in the other direction too
If it only failed one way you could treat it as a floor and move on. It fails both ways, and the second direction is why teams that try to automate this end up ignoring their own tooling.
A registry 404 does not mean the model hallucinated. Frameworks ship virtual modules, bundled subpackages and import aliases that are valid in source and have no standalone registry entry.
The clearest example came out of npm. When the researcher behind a large package-hallucination study could not get his npm findings through the registry's own security channels, he took them to Socket at the end of April. Socket reviewed all 18 npm candidates and published the result in July.
The four highest-volume names among them were @ember/service, @ember/object, @ember/routing and @ember/controller. All four are valid Ember imports that resolve through ember-source. A model emitting @ember/service is writing correct Ember. A registry lookup for that name returns 404.
Socket also found ssh-keys was a real package and metro-evaluator was already security-held, and those six names came out of the exploitable set. The researcher folded the finding into version 2 of the paper as a false-positive class.
I ran the same check against my own machine and got the same result at small scale.
I pulled every package install command my agents proposed in August 2026 out of the local transcripts: 1,100 transcript files, 135 sessions, 121 install invocations, 34 distinct package names. Then I asked npm and PyPI about each one.
Exactly one name 404'd: argos-mcp. It is my own MCP server, linked locally with npm link. Never published. The single registry miss in a month of agent output was a false positive, and it was mine.
The interesting part was the noise. The script I wrote to mine the transcripts was crude in its first version, and it pulled three ordinary words out of the agent's prose that happened to sit next to install. The registry approved all three.
installation is a real package, 23 versions, last touched in 2022. both is a real package, one version, 0.0.0, whose description is the literal string ERROR: No README.md file found!. And binaries returns 200 with zero versions published and no maintainer listed, a name registered in 2018 and holding nothing at all.
Three words that were never package names, waved through by the check that was supposed to catch fabricated package names. One real local package, flagged.
That is a 34-name sample on one developer's laptop, so treat it as an illustration rather than a measurement. It reproduced both error directions anyway.
Switching models does not help
The reflex fix is to have a second model check the first one's suggestion. The research is unusually direct about why that underperforms.
The study Socket reviewed is a replication of the USENIX Security '25 work on package hallucination, run against five current models: Claude Sonnet 4.6, Claude Haiku 4.5, GPT-5.4-mini, Gemini 2.5 Pro and DeepSeek V3.2. Nearly 200,000 prompts. Beyond the per-model rates, it looked for names that every model invents, and found 127 of them.
PyPI Security's prohibited-name list and normalisation defences left 41 of the 109 Python names registrable, and Socket's review took the npm side from 18 down to 12. That is 53 names which all five models produce and an attacker could still register, as of the April 2026 disclosure.
One registration. Four vendors' users.
Three of those names are public in the write-up: css-color-stop, dns-sd and dom-ains. I looked all three up while writing this. Two of them are still free.
css-color-stop was registered on 28 July 2026, six days after Socket published the article that named it. What sits there now is version 0.0.0: one file, 53 bytes unpacked, no dependencies, no install script, no README, no description.
An empty package with nothing that executes is what a defensive registration looks like, and that is the likeliest reading. Somebody saw the disclosure and took the name so that nobody else could. It is worth sitting with anyway, because the mechanism is identical either way. A name travelled from a published security write-up to a claimed npm package in six days, and the only difference between the harmless version of that and the other one is what the publisher decided to put in the tarball.
That 53 is the number that matters, and no single-model study could have found it. Asking Gemini to check Claude's homework does not help when both invent the same name. The 24 August paper measures the family-level version of this: when the primary model and its fallback come from the same family, roughly 84% of the primary's failures recur on the fallback.
The number everyone quotes has expired
While I was reading round this, nearly every blog post and vendor page cited the same two figures: 19.7% of generated packages do not exist, and 43% of hallucinated names recur across all ten reruns. Those come from Spracklen et al., which circulated as a 2024 preprint and was published at USENIX Security '25.
The replication measured current frontier models at 4.62% to 6.10%. The spread between best and worst model collapsed from 16.5 percentage points to 1.48.
Quoting 19.7% in September 2026 describes a model generation that has been superseded. That cuts both ways, though. The rate fell and the shape of the risk got worse, because the models converged. When every vendor's model invents the same 127 names, the attacker's job stopped being probabilistic.
Read the caveats too, because the same study carries real ones. GPT-5.4-mini was tested at minimal reasoning effort and refused 32% of prompts, so its rate is computed over the compliant remainder. The measurements are one week in April against specific model snapshots. And agents that query the registry before suggesting a dependency behave differently from a single model answering a single prompt.
This is a preprint with a vendor correction folded into it.
What to actually check
Existence is the wrong question. These are the ones that separate the four names in my opening table from their real counterparts:
- When was the last release? Every impostor above is dormant: 2012, 2017, 2019. Every real one shipped in the last two years. Staleness plus a name your agent just suggested is the strongest cheap signal there is.
- How many releases, and how many maintainers? One release and no maintainer is not a project.
binarieshas zero versions and returns 200. - Does the description match what you asked for?
haystacksays it searches C structures in process memory. You asked for an LLM framework. The registry told you the truth and the check threw it away by only reading the status code. - Does the import name match the install name?
import cv2installsopencv-python. This mismatch is normal in Python, which is exactly why a lookalike hides in it comfortably. - Commit the lockfile, and install from it in CI. This is the same argument as pinning a version not being the same as pinning a commit. A lockfile stops drift on packages you already vetted. It does nothing about the first install, which is the moment slopsquatting attacks.
- Treat an agent-proposed dependency like a pull request from a stranger. The pre-install checklist for MCP servers is the same ten minutes of work, aimed at a different registry.
None of that is new. It is the vetting that the npm playbook already taught us and that we skip when the suggestion arrives from something that sounds confident.
Which is the actual mechanism here. The model was never guessing at a package name. It produced the most plausible continuation, and a plausible package name looks exactly like a real one. That is the whole attack surface.
tabula is a better name than tabula-py. That is why the model reaches for it, and why somebody registered it in 2012 for something else entirely.
The registry will confirm it exists. It will not tell you the model was wrong.