Skip to content
T threat.cafe

· Priya Venkatraman (editorial persona) · Agent artifact supply chain · on threat.cafe

Slopsquatting when no human types the name: what changes for package policy once agents choose and install dependencies

Slopsquatting is when an attacker registers a package name that AI models tend to invent, then waits for someone to install it. Typo checks do not stop it, because only 13.4% of hallucinated names sit within one or two characters of a real package (Spracklen et al.). Once a coding agent picks and installs dependencies itself, there is no human left to notice an odd name. The fix is a check that runs before every agent install: does this exact package exist, how old is it, is it known bad, and has a person approved anything new?

The question you are actually asking

Your agent just added a line to package.json or requirements.txt. You did not pick that package. You may not even see the line until the pull request. You want to know two things. Could that name be one the model made up? And if it was, could someone already own it?

The answer to both is yes. The rest of this piece explains why, and gives you a decision flow you can put in front of every agent install.

The direct answer

Treat every dependency your agent proposes as unreviewed input. Before the install command runs, a check outside the model should confirm four things:

  • The name exists on the registry the agent is about to use.
  • The package is not brand new. Very young packages get a human look.
  • The name and version are not known bad. That includes registry security holds and malware advisories.
  • A person signed off on any package that is new to this repository.

Name-similarity scanners can stay. They just are not the control that matters here.

How package hallucination works, layer by layer

Layer 1: models invent names, often

The largest study so far, by Joseph Spracklen and colleagues, ran 16 code-generating models on two prompt datasets and produced 576,000 code samples in Python and JavaScript (arXiv abstract). Across those tests the models referenced 2.23 million packages. Of those, "440,445 (19.7%) were determined to be hallucinations" (paper, section 5.1). The study counted 205,474 unique invented names.

The rate varied a lot by model. Commercial models averaged at least 5.2% and open-source models 21.7% (arXiv abstract). The paper is slated for USENIX Security 2025, and its models are from 2024 and 2025. Newer models may do better. Nobody has published a current rerun of the same benchmark, so treat the rates as an order of magnitude, not today's number.

Layer 2: the invented names repeat

The authors took 500 prompts that had produced a hallucination and ran each one 10 more times. "43% of hallucinated packages were repeated in all 10 queries, while 39% did not repeat at all" (paper, section 5.3).

That repeat rate is what makes this an attack and not just a bug. Think of a vending machine that, when you press B4, hands out a snack it does not stock. If it always names the same missing snack, someone can start stocking that slot. An attacker can prompt models, collect the names they keep inventing, and register them.

Layer 3: the invented names are not typos

Typosquatting defences look for names that are close to popular ones, such as reqeusts next to requests. The study measured that distance. Only 13.4% of hallucinated names were within a Levenshtein distance of 1 or 2 of a valid package, and 48.6% scored 6 or higher. In the authors' words, "the majority of hallucinations are not merely trivial typographical errors" (paper, section 5.4).

In plain English, a hallucinated name looks like a plausible new library, not a misspelling. A similarity check has nothing to compare it with.

Layer 4: the agent removes the human

Most slopsquatting advice assumes a developer reads the suggestion and types the install command. The Cloud Security Alliance's April 2026 research note describes the shift. It reports, citing Aikido Security researcher Charlie Eriksen, that a hallucinated name, react-codeshift, spread through 237 repositories via AI-generated agent skills, with downloads driven largely by agents running their own output (CSA Labs, 19 April 2026).

When the agent writes the dependency and runs the install, the review step is gone. The catch is that most teams' controls were built for that review step.

A worked example you can rerun

You can see both outcomes on the public npm registry without installing anything. npm view only reads metadata. These lookups were run on 15 October 2026.

Name looked up                      Registry answer                                    What a policy should do
----------------------------------  -------------------------------------------------  -----------------------
this-package-should-not-exist-zz9q  HTTP 404, no such package                          Block; tell the agent
react-codeshift                     Exists. Created 2026-01-14, one version (1.0.0).   Hold for human review
                                    README: "a placeholder published to prevent
                                    dependency confusion"
unused-imports                      Exists. Version 0.0.1-security only; description   Block: registry hold
                                    "security holding package". OSV MAL-2025-48781:    and malware advisory
                                    version 9.9.0 was malicious

The react-codeshift row shows the ambiguity. The name a model invented now exists, and the README says it was published as a defensive placeholder. This time a defender got there first. A name check alone cannot tell you whether the owner of a newly registered name is a defender or an attacker. Age and provenance can at least tell you to ask.

The unused-imports row shows the other branch: the name was taken by an attacker. OSV report MAL-2025-48781, published 27 October 2025 and aliased to GitHub advisory GHSA-gcxg-769g-4p5h, lists version 9.9.0 as malicious and warns that any computer that installed it "should be considered fully compromised." npm then replaced the package with a security holding package. The CSA note reports it still drew about 233 weekly downloads in early February 2026, as a hallucinated stand-in for eslint-plugin-unused-imports (CSA Labs). Something keeps asking for it.

To repeat the check yourself, read metadata only:

npm view react-codeshift time.created versions description
pip index versions <name>   # PyPI: lists published versions, installs nothing

The decision flow for agent installs

Put this flow in a check that runs before the install command, such as a Claude Code PreToolUse hook on the Bash tool. Anthropic's documentation says a hook can "Exit with code 2 to block the action", and that a timed-out PreToolUse hook does not block unless you set "onFailure": "block" (Claude Code hooks reference). Set that, or your check fails open.

Agent wants to install NAME@VERSION from REGISTRY
|
1. Is NAME@VERSION already in this repo's lockfile or on the team allowlist?
|     yes -> allow, log
|     no  -> go to 2
2. Does NAME exist on REGISTRY, and does VERSION exist?
|     no  -> BLOCK. Return "package does not exist" to the agent.
|            Do not let the agent pick a "similar" name on its own.
|     yes -> go to 3
3. Is NAME@VERSION known bad (malware advisory, registry security hold,
   your org's denylist)?
|     yes -> BLOCK, alert
|     no  -> go to 4
4. Was NAME first published, or VERSION released, inside your age window?
|     yes -> ASK A HUMAN
|     no  -> go to 5
5. Is NAME new to this repository?
|     yes -> ASK A HUMAN (one-time sign-off, then add to allowlist)
|     no  -> allow, log

Three details matter more than they look:

  • Check the right registry. The CSA note reports that 8.7% of Python names hallucinated in the study exist on npm (CSA Labs). Existence on the wrong registry proves nothing.
  • Pick an age window and write it down. The CSA note suggests flagging packages registered within the prior 30 to 90 days. Choose a number your team will tolerate. A longer window catches more but asks more often.
  • Return a clear message on a block. If the hook says only "denied", the agent may try a different invented name. Say the package does not exist and that a human must choose.

Where the simple explanation stops being true

Known-bad lists lag. A freshly registered slopsquat has no advisory yet. That is why steps 4 and 5 exist. The "unknown" state needs its own rule, not a pass.

Age is not intent. Old packages get hijacked too, as the axios compromise of 31 March 2026 showed. An age gate handles hallucinated names. It does not replace the known-bad check.

Private registries change the question. If your agent resolves through an internal mirror, step 2 asks whether the mirror has it. Make sure the mirror does not proxy any public name on first request, or you have moved the problem, not fixed it.

Vendor numbers are not study numbers. Endor Labs states that 34% of AI-recommended dependencies are hallucinated (Endor Labs, 2 September 2026), but the page gives no sample size or method. Use the peer-reviewed figures for planning.

Decision checklist

  • Your agent's install commands pass through a check outside the model.
  • The check fails closed on timeout.
  • Non-existent names are blocked with a clear message.
  • Known-bad names and registry holds are blocked.
  • New or very young packages wait for a person.
  • Every decision is logged with the package, version and rule that fired.

If you want a known-bad source that covers skills and MCP servers as well as npm and PyPI, the threat.cafe early-access list is built for exactly this pre-install check.

Sources

#slopsquatting #hallucinated-packages #coding-agents #npm #pypi

All posts