Catching Hallucinated Imports Before pip install

AI assistants invent package names that don't exist; one study found 19.7%. BrassCoders flags every unresolvable import before the install runs.

Copper Sun Brass Team · · 4 min read
securityoss-core

Your AI assistant suggests a pip install. The package name looks right. It doesn’t exist. A 2025 USENIX Security study found 19.7% of AI-recommended packages aren’t real — and that gap is now an attack surface. Lasso Security registered one hallucinated name as a proof of concept and watched it pull 30,000+ downloads. BrassCoders flags any import that doesn’t resolve on the registry, before you run the install.

The Import That Resolves to Nothing

BrassCoders treats a hallucinated import — a package name an AI assistant invented that doesn’t exist on the registry — as a bug class human-written code almost never produces. The name reads as plausible, passes a visual review, and fails only when someone actually runs the install.

The mechanism is straightforward. AI assistants generate package names the way they generate everything else: by predicting what looks right. A name that resembles a real library. A slight misspelling. A package that exists on npm but not PyPI. All of them read naturally in an import line. A reviewer scanning the diff sees import followed by a sensible-looking name and moves on. The failure surfaces later as an ImportError, or it doesn’t surface at all, because someone registered the name in between. The full problem write-up lives in When AI Invents Libraries.

Why a Missing Package Is a Security Problem, Not a Typo

BrassCoders treats a hallucinated import as a supply-chain exposure rather than a harmless mistake, because the invented name is squattable. Models hallucinate the same plausible names repeatedly, which is exactly what makes the attack economical.

A 2025 USENIX Security study put the hallucination rate at 19.7%. Lasso Security showed the payoff: they registered a hallucinated huggingface-cli package as a proof of concept, and 30,000+ machines installed it. A real attacker registers the name, publishes a malicious payload, and waits for the next developer whose assistant suggests that import. The install runs arbitrary code. The deeper research on this attack class is in the slopsquatting research.

How BrassCoders Flags Them

BrassCoders’s phantom-import check parses every import in your code and asks the public registry whether each package actually exists, flagging the ones that don’t before the install runs. The command is one flag on the scan:

brasscoders scan --check-package-hallucination

It validates names against PyPI, npm, and pkg.go.dev, so a hallucinated Python, JavaScript, or Go import gets caught the same way. The check is deterministic — the same imports produce the same flags, with no model in the loop deciding what counts.

One honest detail: this is the single BrassCoders check that touches the network. To know whether a package exists, it has to send each unknown package name to the registry. The OSS core is offline-first by default and makes zero outbound calls, so the registry check is off unless you opt in with --check-package-hallucination. Passing --offline forces it back off and keeps the scan fully local. You choose: a fully offline scan, or the registry check that needs connectivity.

Where the Check Ends and Your Judgment Begins

BrassCoders confirms whether a package exists; it does not vouch that an existing one is safe. The unresolved name is a fact it reports. Whether to trust a package that does resolve is a judgment it leaves to you and your AI assistant — the deterministic layer reports, the context-aware layer decides.

That boundary is deliberate. A real package can still be compromised, abandoned, or typosquatted close to a legitimate name, and verifying that is software composition analysis — the territory of tools like Socket and Sonatype. BrassCoders covers the part with a clean deterministic signal: the name either resolves or it doesn’t. The adjacent attack, where a real internal name collides with a public one, is covered in the dependency confusion research.

Run the Check

Install BrassCoders and add the flag to a scan. Because the check queries the registry, run it without --offline:

pipx install brasscoders
brasscoders scan --check-package-hallucination

Flagged imports land in .brass/ai_instructions.yaml alongside the rest of the findings, ready to hand to Claude Code or Cursor. For the full picture of every detector BrassCoders runs, see what BrassCoders detects.

Frequently Asked Questions

How often do AI assistants hallucinate package imports?

A 2025 USENIX Security study measured 19.7% of AI-recommended packages don't exist on the registry. The rate is steady enough that attackers pre-register the invented names — Lasso Security's proof-of-concept hallucinated huggingface-cli package drew 30,000+ downloads. BrassCoders flags any import that doesn't resolve on the public registry.

How does BrassCoders check for hallucinated imports?

With brasscoders scan --check-package-hallucination, it parses every import in your code and asks the public registry (PyPI, npm, or pkg.go.dev) whether each package name actually exists. Anything that returns not-found is flagged before pip install runs. The check is deterministic: the same imports produce the same flags every time.

Why isn't the hallucination check on by default?

It's the one BrassCoders scan that touches the network — it has to ask the registry whether a package exists, which means sending each unknown package name over the wire. The OSS core is offline-first by default (zero outbound calls), so the registry check is an explicit opt-in via --check-package-hallucination. Running with --offline forces it back off.

Does a package existing mean it's safe to install?

No, and that's the honest limit. The check confirms a package exists on the registry; it doesn't vet whether that package is malicious. A real-but-compromised package is a separate problem (software composition analysis). BrassCoders catches the non-existent and squattable names; safety review of packages that do exist is a different layer, handled by tools like Socket or Sonatype.

What's the difference between a hallucinated import and slopsquatting?

A hallucinated import is the AI inventing a package name that doesn't exist. Slopsquatting is the attack that exploits it: a malicious actor registers the hallucinated name, so the next developer who installs it gets malware. BrassCoders flags the import at the unresolved-name stage — whether or not someone has squatted the name yet, the flag is the same.