Hallucinated packages, slopsquatting, and dependency hygiene
Language models invent package names. Attackers have noticed, and register them. Here is the check that takes four seconds.
Ask a model for a library that does something slightly unusual and it will sometimes give you a package name that sounds exactly right, has a plausible API, and does not exist.
This is a well-documented behaviour, it happens across every model family, and the same non-existent names recur — the failure is not uniformly random, which is the part that matters. A predictable hallucination is a namespace an attacker can pre-register and wait in.
The industry name for that attack is slopsquatting, by analogy with typosquatting. It is cheap to execute, it targets an install command that people run without thinking, and Python is a particularly good target because pip install runs arbitrary setup code from an index anyone can publish to.
Why models do this#
Package names are compositional and predictable: <thing>-<qualifier>, py<thing>, <thing>-python, <framework>-<feature>. A model that has seen thousands of real names generalises the pattern and produces new ones that fit it perfectly. It is the same generative behaviour that makes it good at naming your functions.
It gets worse in three specific situations, worth knowing because they are where to pay attention:
- Niche requirements. "A library for parsing HL7 v2 into pydantic models" — sparse training data, high invention rate.
- Version drift. A package that was real, then renamed or absorbed.
sklearnversusscikit-learn,PILversuspillow, and dozens of smaller cases. - Wrong ecosystem. A real npm package name suggested as a Python one, because the concept exists and the model has crossed the streams.
The four-second check#
Before any uv add or pip install that you did not think of yourself:
# does it exist, and is it what you think it is?
uv pip index versions <name> # or: pip index versions <name>Then look at the PyPI page and ask three questions:
- When was it first published? A package solving an old problem that appeared last month is a red flag.
- How many releases, and over how long? One release, ever, is a red flag.
- Does the repository link go anywhere real, with commit history and issues from other people?
That is genuinely all it takes, and it catches essentially every instance of this attack.
Beyond hallucination: the dependency you did not need#
The more common and more boring problem is that agents add dependencies too readily. Asked to parse a date, retry a request or flatten a list, a model frequently reaches for a package where the standard library or three lines would do — because the training data is full of code that does exactly that.
Every dependency you add is a supply-chain surface, a version constraint on your other dependencies, and a thing that will eventually be unmaintained. The Python standard library is large and covers more than most generated code assumes:
| Generated reaches for | Often unnecessary because |
|---|---|
python-dateutil | datetime.fromisoformat handles ISO 8601 since 3.11 |
requests | fine, but httpx if you need async; urllib.request for one call |
six, future | Python 2 compatibility shims. Delete on sight. |
attrs alongside pydantic | pick one; dataclasses may be enough |
| a retry library | tenacity is good, but a 6-line loop is often better |
toml | tomllib is stdlib since 3.11 |
Add a line to your AGENTS.md: "New dependencies need a sentence in the PR description justifying them. Prefer stdlib." It works, and it makes the decision visible at review time.
Pin, lock, and read the lockfile diff#
uv add httpx # writes pyproject.toml AND uv.lock
git diff uv.lock # read this. it is the actual supply chain.A one-line change to pyproject.toml can be a forty-line change to the lockfile. The lockfile diff is where you see the transitive dependencies you just accepted, and it is the only place you see them.
Automate the rest#
uv add --dev pip-audit
uv run pip-audit # known CVEs in your resolved treeWire it into CI rather than the agent loop — it needs network access and it is too slow for a per-edit check. Weekly, plus on every lockfile change, is the right cadence.
Also worth enabling: your host's automated dependency updates (Dependabot, Renovate). Not because the updates matter individually, but because a repo where updates arrive continuously is one where a security update can actually be merged in an afternoon.
The whole policy, in four lines
- Package installs go behind a confirmation, never on the allowlist.
- Unfamiliar name? Check first published, release count, repository.
- Read the lockfile diff.
pip-auditin CI.
Common questions#
How often do models actually invent package names?#
Often enough that it is worth a systematic check rather than vigilance. Published research on this has found meaningful hallucination rates across model families, with a substantial share of invented names repeating across runs — and that repeatability is what makes the attack economic. The rate is lower on frontier models than it was, and it is not zero.
Is this specific to Python?#
No — npm has the same problem and a larger attack surface. Python is a particularly attractive target because installation can execute arbitrary code and because pip install is a command people run reflexively without reading.
Does a lockfile protect me?#
From version drift and from a compromised later release, yes. From installing a malicious package in the first place, no — the lockfile records whatever you added. The check has to happen at uv add time, which is exactly why that command belongs behind a confirmation.
What if the package genuinely does not exist but I need what it does?#
Good outcome, actually: it means you now know to check whether the stdlib covers it, and if not, whether the real library is called something else. Ask the agent for two or three alternatives and verify each — the second suggestion is usually the real one.
Get the Python agent pack
A battle-tested AGENTS.md, the review checklist, and the failure-mode cheat sheet for Python. One email, then occasional updates when the tooling shifts. No course pitch.
AGENTS.md now — no email needed.
Disclosure: some links on this page are affiliate links. If you buy something through one, we earn a commission at no extra cost to you. We only list tools we would tell a friend to use, and we say so when we have not used something ourselves. This is how the site stays free and ad-light.