
In brief
Hallucinated package names are predictable, which makes them registerable. Check that the package exists, that it is the one you meant, and that installing it does not run code you never read.
Ask an AI assistant for a small utility and it will often answer with a confident import and an install command. Sometimes the package does not exist. It is not random noise: the same invented names show up again and again across repeated prompts, which is exactly the property an attacker needs to register a name in advance and wait.
That attack is called slopsquatting, and the defense is not "stop using AI assistants". It is to verify the name before it reaches your package manager, and to make installation harder to weaponize.
01What slopsquatting actually is
The pattern has three parts. A model produces a plausible package name. That name is stable enough to be predictable across users and runs. A registry lets anyone claim an unused name.
Studies of code-generating models have put hallucinated recommendations at roughly one in five of all suggested packages. Duplicate-name typosquatting exploits a human mistyping a known package; slopsquatting exploits a machine confidently inventing one. Because the model presents its suggestion with the same tone it uses for a real library, the mistake is easy to copy into a terminal without a second thought.
Existence is not the same as legitimacy
An attacker can register a hallucinated name after it appears in model output. "npm found it" only proves someone claimed the name — not that the code is safe or that it is what the model meant.
02Why hallucinated names are predictable
Models generate names the way they generate any other token: by continuing the most plausible pattern. For a date library that means concatenating date and a common suffix; for a CLI helper, @scope/tool-name. The output is not the real package, but it looks exactly like one.
Because decoding is guided by the same statistics each time, the same prompt tends to produce the same invented name. That predictability is the vulnerability. It also means the fix cannot be "use a better prompt" — a model that never hallucinates a name is not available, so verification must live in your workflow.
03Verify a name before you install it
Make this a reflex, and the whole class of attack gets much harder.
- Ask the registry directly. A 404 ends the conversation.
npm view left-pad version repository.url maintainers time.created
# version = '1.3.0'
# repository.url = 'git+ssh://git@github.com/stevemao/left-pad.git'
npm view left-paad version
# npm error 404 Not Found - GET https://registry.npmjs.org/left-paad - Not found
python3 -m pip index versions requests
# requests (2.32.5)
# Available versions: 2.32.5, 2.32.4, 2.32.3, ...
- Match the package to the project you expect. Read
repository.urland the maintainer list. A library with a source repository, a changelog and years of releases looks different from a name registered last week with no homepage. - Check the shape of the release history. A package whose entire version list appeared in a single day is a red flag, and so is a wrong-looking version like
99.0.0chosen to look mature. - Compare the suggestion to what the ecosystem actually uses. If the assistant proposes a wrapper for a well-known library, check whether that library already exposes the feature natively. Hallucinations often exist to fill a gap that does not exist.
04Lockfiles, install scripts and the execution trap
Installing a package is not a read-only action. Lifecycle scripts run on install, and a malicious package can use them to execute code before your tests ever run.
- Commit and review lockfiles.
npm ciinstalls exactly what the lockfile pins, so a reviewed lockfile is a control. An unreviewednpm install <typo>rewrites it. - Skip scripts on first contact. Add a dependency with
npm install --ignore-scripts, inspect it, then install normally if you trust it. - Use a hash-pinned install for Python.
pip install --require-hashes -r requirements.txtrefuses a package whose bytes differ from the recorded hash. - Keep an install-time review step. A lockfile diff in code review is one of the cheapest places to notice a name that does not belong.
npm ci --ignore-scripts
npm ls --all | head -40
git diff -- package.json package-lock.json
Diff the lockfile, not just package.json
A new top-level dependency often drags in a dozen transitive packages. The lockfile diff shows all of them, and that is where a name you never approved will appear.
05Harden the workflow, not just the moment
Individual checks catch individual mistakes. A few structural controls catch the class.
| Control | What it stops |
|---|---|
| Private registry proxy with an allowlist | Unknown names never reach developers |
| Required lockfile review | Sneaked-in transitive dependencies |
| Disable lifecycle scripts in CI | Install-time code execution |
| Dependency scanning in CI | Known-malicious packages and CVEs |
| Internal package naming rules | Confusion between internal and public scopes |
| Provenance / attestation checks | Typosquats without a real build pipeline |
The registry proxy is the highest-leverage one: if a package is not already mirrored or allowlisted, the install fails and a human decides. That turns a silent supply-chain risk into a routine review.
06If you already installed the wrong package
Treat it as an incident, not a typo. Remove the dependency, then check what the install actually did: review postinstall and preinstall scripts in node_modules/<name>, look for new outbound network calls, rotate any credentials that were present in the environment during install, and check whether the lockfile was committed and pushed. On a shared repository, the compromised lockfile is the part that spreads.
07Common mistakes and fixes
| Mistake | Why it fails | Fix |
|---|---|---|
| Installing straight from the chat answer | No registry check happens | Run npm view or pip index versions first |
| Trusting a package because it exists | Attackers register hallucinated names | Check publisher, repo and release history |
Reviewing only package.json | Transitive packages hide there | Review the lockfile diff |
| Letting CI run install scripts | Malicious code executes during build | Use --ignore-scripts, or sandbox the install |
| Assuming a scoped name is internal | Public scopes can look internal | Enforce an explicit internal scope |
The habit that matters is small: never let a model's suggestion become a dependency without one registry lookup. The rest of the hardening exists for the times you are tired, rushed and ready to trust the output.
Validate package.json and lockfile fragments before they reach your build.
JSON ValidatorFrequently asked questions
What is slopsquatting?
Slopsquatting is registering a package name that an AI model invents, so that the next developer who copies the model's suggestion installs the attacker's code instead of nothing.
Do AI assistants really invent package names?
Yes. Studies of code-generating models found that roughly one in five recommended packages did not exist in the registry, and that the same invented names recur across repeated prompts.
Is it safe if the package exists on npm?
Existence is necessary but not sufficient. A name can exist because an attacker registered it after seeing it hallucinated, so also check the publisher, the repository link, the age and the download pattern.
What is the fastest way to check a package?
Ask the registry directly before installing. For npm that is `npm view <name>`; for Python it is `python -m pip index versions <name>`. A 404 is a stop signal.
Should I disable install scripts?
For untrusted or newly added dependencies, yes. `npm install --ignore-scripts` skips lifecycle scripts, which are a common execution path for malicious packages, then you can install normally once the dependency is reviewed.
Related articles
- Prompt injection is the new SQL injection
The other way untrusted model output reaches your system.
- How to format, validate and minify JSON
Manifests and lockfiles are JSON — validate them.
Related tools
- JSON Validator
Catch a broken manifest before install.
- JSON Schema Generator
Turn your dependency policy into a schema.
- JSON Formatter
Read a lockfile diff without squinting.
- Diff Checker
Review lockfile changes line by line.