How Software Development ChangedLesson 69 of 87

Contents

How Software Development Changed

Lesson 69 of 87. Sign in to keep your place.

Module 8 · Provenance, security and the unsettled law

The package that did not exist until an attacker made it

9 min read

A new door, opened by a specific failure

Ask for code that parses a config format and you may get an import for a library that has never existed. The model produced a name of the right shape (plausible prefix, plausible suffix, the naming convention of that ecosystem) because that is what it does. The name is fiction.

On its own that is a broken build, and broken builds are cheap. The problem is what happens next. An attacker who knows which names get invented can register them. Then the fictional import resolves, the install script runs, and code the attacker wrote is executing on a developer machine with that developer’s credentials.

The name that stuck for this is slopsquatting, by analogy with typosquatting.

Why it is exploitable rather than merely annoying

The attack needs the hallucinations to repeat. If every invented name were unique noise, an attacker would have nothing to pre-register.

A 2025 study presented at USENIX Security examined around 576,000 generated code samples across a range of models and found that roughly a fifth of the package references did not exist. The finding that matters for security was the second one: a large fraction of those invented names came back again on repeated runs of the same prompt. That repetition is the exploitable property. It converts a random error into a predictable target list that anybody can harvest by running prompts.

Treat those figures as a snapshot. Models change, rates move, and the paper measured particular models at a particular time. The mechanism is what persists: a generator is optimising for plausibility, and a plausible package name is exactly what a squatter needs.

The older cousin, still live

Dependency confusion, demonstrated by Alex Birsan in 2021, is the related trick. Your build refers to an internal package: acme-billing-utils, which exists only on your private registry. An attacker publishes a package with that name to the public registry with a higher version number. Many default resolvers prefer the higher version wherever they find it, so the public one wins.

Generated code makes this worse in an unglamorous way: it invents internal-sounding names freely, and those names end up committed and visible in public repositories, which is the reconnaissance step done for free.

What to actually do, in order of value

Check before installing, not after. Thirty seconds, and it is the whole defence.

Bash
npm view left-pad-config          # does it exist, who published it, when
pip index versions requests-toml  # same question for PyPI

Look at four things: publication date, download counts, whether the repository link resolves to a real project, and the maintainer’s other packages. A package first published last Tuesday with forty downloads and no repository is not a library, whatever it is called.

Install from a lockfile with hashes, always. npm ci uses the lockfile and its integrity hashes; npm install may resolve something new. In Python, pip install --require-hashes -r requirements.txt refuses anything whose hash does not match. Container images by digest, never by :latest.

Scope your internal packages. Publishing under an organisation scope (@acme/billing-utils) makes the public namespace collision impossible. Configure the resolver so scoped names only ever resolve to your registry.

Scan continuously. osv-scanner, trivy, npm audit, cargo audit, pip-audit are all free and open source, and all of them run in a pipeline in seconds.

Treat every new dependency in a generated diff as its own review item. Module two covered how to review a dependency change; the addition here is narrower. Before anything else, ask the dumb question: does this package exist, and did it exist last month?

What does not work

Asking the model whether the package is real. It will answer confidently either way, and the answer comes from the same distribution that produced the name.

Relying on the install failing. Once a squatter has registered the name, the install succeeds: that is the point of the attack.

A blanket ban on new dependencies. It sounds decisive, it survives about a week, and it pushes people into copying source into the repository, which is worse because it never gets patched.

The limitation

None of this catches a compromised version of a package you already trust, which has been the mechanism behind several of the largest supply-chain incidents. Lockfiles pin what you had; they do not tell you the maintainer’s account was taken over last night. That class of attack is older than generated code and is not made worse by it, but it is also not addressed by anything in this lesson.

The check is not “is this a good library”. It is “is this a library”. That question used to be answered for free by the fact that a human had heard of it.

Every lesson here is open. Your progress is recorded once you pass the AI at Work exam.

Check your understanding

Why does the repetition of hallucinated package names across runs matter more for security than the hallucination rate itself?

Pick the one you would defend. Your answer stays private.

Next lesson · 10 minInsecure defaults, inherited

Stuck on something?Ask Larissa, your AI tutor

How to cite: Addaly (2026) ‘The package that did not exist until an attacker made it’, in How Software Development Changed. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/how-software-changed/packages-that-do-not-exist (Accessed: 13 October 2026).