Short answer. Ask an AI tool for code and it will sometimes tell you to install a package that does not exist. Attackers watch for those made-up names, claim them on npm or PyPI, and wait. The next person who gets the same tip installs their code instead of nothing. The attack has a name now. It is called slopsquatting.
Two things make this worse than it sounds. The bad code runs when you install, not when you ship. And your scanner will not flag it, because there is nothing on file to flag yet.
The trap in one line. A fake package is not a known flaw. It is a brand new upload with a clean record. Tools that match your code against lists of known flaws have nothing to match it against, so they pass you.
Where the numbers come from
Two studies matter here, and they say different things about the same problem.
The first is Spracklen and colleagues, published at USENIX Security in 2025 and given that year's Distinguished Paper Award. The team ran 16 models over 576,000 code samples in Python and JavaScript. They counted how often a model named a package that was not on the index. The rate was at least 5.2% for paid models and 21.7% for open ones. Across the whole run they logged 205,474 made-up names.
The second is newer and much smaller. A 2026 replication by Aleksandr Churilov re-ran that method on five recent models across 199,845 prompts. It is a preprint by one independent researcher, it has not been peer reviewed, and the tests ran over one week in April 2026. Read it with that in mind. We do, and we still think it is the more useful of the two for anyone shipping today.
Its headline: the gap between models has closed. Where the 2025 study saw a spread from 5.2% to 21.7%, this one saw 4.62% to 6.10%. Every model got closer to the same number. None of them got to zero.
| Finding | 2025 study (peer reviewed) | 2026 replication (preprint) |
|---|---|---|
| Models tested | 16 | 5 |
| Code samples | 576,000 | 199,845 |
| Rate of made-up names | 5.2% paid, 21.7% open | 4.62% to 6.10% |
| Worse language | JavaScript | Python |
| Names every model invents | not measured | 127 |
This is not a typo problem
Typosquatting is old. Someone claims a name one letter away from a real one and waits for slips of the finger. It works, but it needs you to make a mistake.
Slopsquatting does not. You type the name correctly. You type exactly what you were told to type. The mistake was made upstream by the model, and it was made the same way for everyone who asked the same question. That is the shift. The attacker no longer waits for a rare slip. They wait for a common answer.
It is also not the same as the code-quality problems in AI-written code. Those live in code you can read. This one lives in a single install line that looks fine.
The bad code runs at install, not at launch
This is the part most write-ups skip, and it is the part that decides how bad a bad day gets.
npm runs build steps from the package itself during install. The npm docs list them as preinstall, install and postinstall, and they run by default unless you pass --ignore-scripts. Python does much the same thing when it builds from source.
So the chain is short:
- You paste the install line you were given.
- Your package tool fetches that name from the public index.
- The package runs its own setup step on your machine.
- You read the error, notice the package is wrong, and remove it.
Step four is too late. Step three already ran. It ran with your shell, your files and whatever keys sit in your environment. Nothing was shipped. Nothing was merged. It does not matter.
The same logic applies on a build server, which is worse, because a build server usually holds better keys than a laptop does. If you are setting one up, our notes on what to add to a build pipeline cover where this fits.
Your scanner is looking the wrong way
Here is the claim we want to be most direct about, because it applies to our own product as much as anyone else's.
Most tools that check your packages work by matching what you have installed against public lists of known flaws. That is a good design. It catches an old library with a real reported problem, and it catches it fast. Every tool in that class works roughly this way.
Now think about what a fake package looks like on that list. It went up last week. Nobody has reported it. It has no entry, no score and no past. The match runs, finds nothing, and the tool reports nothing. The tool is not broken. It answered the question it was built to answer.
The same gap sits one layer up. A scanner that probes your live site, like the network scanners founders tend to buy first, looks at what your service exposes. Code that ran on a laptop during install never touched that surface. And a code analysis tool, the kind compared in this scanner write-up, reads the code in your project. The fake package's code was never in your project. It ran from a folder your tool treats as someone else's.
Say it plainly. Three whole classes of security tool can all pass a project that was already compromised at install. This is not a gap in any one product. It is a gap in where all of them look.
Switching to a better model does not fix it
The most common advice on this topic is to use a stronger model. The 2026 preprint has the sharpest finding against that, and it is the reason we picked this topic.
The author took the names each of the five models made up and looked at the overlap. Not the rate. The names. There were 127 names that all five models invented. Same names, different makers.
He then sent the list to PyPI's security team and to Socket, who each checked which of those names an attacker could still claim. Some were blocked by naming rules. Some were already taken. After both reviews, 53 were still open: 41 on PyPI and 12 on npm.
Read that as an attacker would. One upload. One name. It lands for users of every one of those five models at once. The cost does not go up when the number of models goes up. So the plan of switching tools does not move you out of the way, because the name you get told to type is the same name.
The reason is dull, which is why it is stable. Models learn from the same public writing. When enough guides call a library by its import name rather than its install name, every model that read those guides lands on the same wrong answer. It is not a random slip. It is a shared habit.
Python is now the worse side
The 2025 study found JavaScript worse and put it down to npm's larger, messier name space. The 2026 run found the opposite, on all five models, by between 2.73 and 4.13 points.
The author's suggested reason is worth knowing even if the finding does not hold up. Python names have more shapes. One project can sit behind a dashed name, an underscored name, a dotted name and a suffixed name, all live at once and all meaning different things. A model that is fluent but not careful lands on a shape that reads right and is not.
If your product is a Python service with a JavaScript front end, that is the side to check first. It is also a good reason not to assume that what you learned about npm in 2024 still describes the risk.
The fake names look better than the real ones
This is the detail that should change how you read a pull request. The names that come up most are not gibberish. They are the name you would have guessed.
| Name the model gave | Index | Real name |
|---|---|---|
aws-cdk | PyPI | aws-cdk-lib |
objc | PyPI | pyobjc |
rest-framework | PyPI | djangorestframework |
opengl | PyPI | PyOpenGL |
openstack | PyPI | openstacksdk |
Every row there was invented by all five models in the 2026 run. Look at the first one. If you knew the tool was called AWS CDK, aws-cdk is the name you would expect. It is the name a reviewer would skim past. It is the name a teammate would defend.
That is why "just look at it" is not a control. The whole failure works because the wrong name reads better than the right one.
See what an outsider sees
Our free scan reads a live URL in about 30 seconds and returns a Launch Readiness Score out of 100 across security, reliability, performance and monitoring.
Run a free scanWhat our own scan does and does not see
We publish our method, so we will be exact about this rather than vague.
Our security checks include known-flaw matching on your packages, drawn from open databases. That check does what the section above describes. It is good at old libraries with reported problems. It would not flag a package that went up last week with no report against it. Nobody's would.
Our free scan reads a live URL. A package that ran a setup step on a laptop in March leaves no mark on a public page in September. So a clean score from us is not a statement about this risk. We would rather say that here than let you read the score as cover.
Where a scan does help is that it tells you what an outsider can already reach: exposed keys, missing auth, absent rate limits, weak headers. Across the 700+ AI-built apps we have scored, the average came out at 44 out of 100, and the usual causes were missing security headers, no rate limiting on login routes, and keys left where a browser can read them. If a fake package did run, and did take a key, those are the doors it walks through next. That part we can see. Our paid audit adds a senior engineer to the same four dimensions, which is a different depth, not a different lens.
Six checks you can run today
None of these need a new tool or a budget line.
- Look the name up before you install it. Open its page on npm or PyPI. Check the first release date, the download history, and whether a source repository is linked. A real library with a plausible name has years behind it. A name claimed three weeks ago with no source link is the shape of this attack.
- Turn install steps off by default. Use
npm install --ignore-scripts, or set it in your npm config so you do not have to remember. Most packages do not need a setup step. The ones that do will tell you loudly. - Install from the lock file on every build server.
npm cineeds a lock file to exist, fails if it disagrees with your package file, and never writes back to it. That turns a silent swap into a failed build, which is what you want. - Read the diff of the lock file, not just the code. A new name arriving in a lock file is a change to what runs on your machines. Treat it like a change to your login route. If you cannot say who added it and why, do not approve it.
- Check Python first if you ship both. Then check the dashed and underscored forms of every name you were given, because that is where the shapes blur.
- Write the rule down for the whole team. A one-line rule that new names get looked up beats a tool nobody set up. Our checklist for teams using AI editors and our notes on working with coding agents both have a place to put it.
If you want to go past a rule, the tools worth adding are the ones that judge a package by its own past rather than by a list of known flaws. That is a different question from the one most scanners answer, and it is the right question here. It also belongs on the same list as the rest of your pre-launch checks.
What we are not claiming
Three limits, stated rather than buried.
We did not measure this ourselves. Every rate on this page comes from the two studies named above. We ran no models and counted no names. We read both papers and checked the npm docs directly.
The 2026 numbers are one week in April. Models change without notice. The author also flags that the prompts he used had been public since early 2025, which may have pulled the rates down, and that one model ran at its lowest effort setting and refused about a third of the prompts. His own paper says to read that model's number with care. So do we.
Tool use may change the picture, and nobody has measured that yet. The 2026 run tested plain model replies. It did not test agents that can search an index before they answer, which is how agent-style tools and many editors now work. The author says so, and calls it future work. So if you use an agent-style editor rather than a chat box, the honest position is that we do not know your rate. Not that it is zero.
We would rather leave that open than give you a number we cannot source. The rule that keeps invented figures off this page keeps invented comfort off it too. If the terms here are new, our plain-English glossary defines them, and our guide to auditing AI-written code covers the wider job this sits inside.
The habit worth keeping. One question, asked every time a new package name shows up in a diff: where did this name come from, and does it have a past? That question costs ten seconds and closes most of this.
Frequently asked questions
What is slopsquatting?
It is a supply chain attack that starts with an AI mistake. A code tool names a package that does not exist. An attacker who has seen that same made-up name claims it on npm or PyPI and puts their own code behind it. The next person who gets the same suggestion types it in and installs the attacker's package. You did not mistype anything. You followed the instruction you were given.
Will my dependency scanner catch a fake package?
Almost certainly not. Scanners of that kind compare what you have installed against public lists of packages with reported flaws. A package uploaded last week has no report, no score and no history, so there is nothing on the list to match. The scan comes back clean because the question it asks is whether your packages have known problems, not whether your packages should be there at all.
When does the harmful code actually run?
At install time, before you ship anything. npm runs preinstall, install and postinstall steps from the package itself during a normal install, and they run by default unless you pass --ignore-scripts. Python does much the same when it builds from source. So noticing the wrong name afterwards and removing it does not undo anything. The code already ran with your shell, your files and your keys.
Does switching to a better AI model fix this?
Not on its own. A 2026 preprint that re-ran the original study on five recent models found 127 package names that all five models invented, and 53 of those were still free for an attacker to claim after both registries reviewed the list. That means one upload can reach users of several different AI tools at once. Changing which model you ask does not change the name it tells you to type.
Is Python or JavaScript more exposed?
The answer flipped. The 2025 study found JavaScript worse. The 2026 replication found Python worse across all five models it tested, by between 2.73 and 4.13 percentage points. The suggested reason is that Python package names come in more shapes, with dashed, underscored, dotted and suffixed versions of the same project all live at once, so there are more plausible wrong answers to land on.
What is the single fastest check I can make?
Open the package page on npm or PyPI before you install, and look at three things: the first release date, the download history and whether a source repository is linked. A real library with a believable name has years behind it. A name claimed a few weeks ago, with no linked source and almost no downloads, is the exact shape of this attack. The check takes about ten seconds.
Research sources
- We Have a Package for You! A Comprehensive Analysis of Package Hallucinations by Code Generating LLMs (USENIX Security 2025, Distinguished Paper Award), reference for the 16 models and 576,000 code samples across Python and JavaScript, for the rate of hallucinated packages being at least 5.2 percent on commercial models and 21.7 percent on open-source models, for the 205,474 unique hallucinated package names recorded, and for package hallucination being characterised as a novel form of package confusion attack against the software supply chain.
- The Range Shrinks, the Threat Remains: Re-evaluating LLM Package Hallucinations on the 2026 Frontier-Model Cohort (arXiv preprint, not peer reviewed), reference for the replication across five frontier models and 199,845 generations run between 22 and 28 April 2026, for the compressed rate range of 4.62 percent to 6.10 percent, for the Python-over-JavaScript gap of 2.73 to 4.13 percentage points inverting the 2024 finding, for the universal-hallucination set of 127 names shared by all five models, for the residual registrable surface of 53 names (41 on PyPI, 12 on npm) after review by PyPI Security and Socket.dev, for the top hallucinated names including aws-cdk, objc, rest-framework, opengl and openstack, and for the author's own stated limitations covering the one-week measurement window, possible prompt-corpus leakage into training data, the lowest-effort setting and 32.14 percent refusal rate on one model, and the absence of any test of agentic or retrieval-backed configurations.
- npm Docs: npm-install, reference for the --ignore-scripts flag and for build scripts being run by default during install.
- npm Docs: scripts, reference for preinstall, install and postinstall being the lifecycle scripts that run for installed packages.
- npm Docs: npm-ci, reference for npm ci requiring an existing package-lock.json, exiting with an error when the lock file and package file disagree, and never writing to either file.
- Jai Mittal, Founder & CTO, Launch Ready Code — Proprietary data from 700+ AI-built app security audits, 2025–2026. Average Launch Readiness Score: 44/100.