AI Package Hallucinations: Verify Before You Install12 min read2,384 words

AI Package Hallucinations: Verify Before You Install

AI coding tools can suggest packages that do not exist. Learn how phantom-deps checks dependencies before installation and fits into your workflow.

AI package hallucinationsphantom-depsslopsquattingPython dependency scannernpm package security
AI Package Hallucinations: Verify Before You Install

Before You Install an AI-Suggested Package, Check That It Exists

An AI coding assistant can spit out a function, a matching import, and even a dependency file in seconds. The danger is that the package name can look totally legitimate while being completely made up. If you install it without checking, you're basically betting that the suggestion is real - right inside your development environment.

This isn't just a "code quality" nit. Research presented at USENIX Security 2025 looked at 2.23 million package references from 16 large language models and found that 19.7% pointed to packages that had never been published. That doesn't mean every project will see one in five fictional dependencies, but it does mean verification is worth the minute or two - especially when the dependency list came from generated code, not from a source you already trust.

You don't need a full-blown security program to reduce the risk. A quick pre-install check can answer two practical questions: does the package exist, and was it published very recently? In this article, I'll walk through the risk, how the open-source tool phantom-deps approaches it, how to run it in a project, and what the checks do (and don't) tell you.

Why an Invented Package Name Creates a Security Risk

AI-generated code usually comes with dependencies attached. You ask for a small Python script or a JavaScript utility and you get source code plus something like a requirements.txt or package.json. The list looks "official" because it's formatted correctly - but that formatting doesn't prove every dependency is real, the right choice, or safe.

Language models generate text from patterns. A package name that resembles a familiar library can fit the patterns even when no such project exists on PyPI or npm. The model might blend a believable prefix and suffix, mix up an import name and the actual package name, or invent a wrapper that sounds like something the ecosystem "should" have.

The USENIX numbers make this more than a rare typo problem. In their dataset, about one in five references pointed to packages that hadn't been published. Again, that's study-level data - not a universal rule - but it's enough to make "does this exist?" a sensible first step when the dependency comes from an assistant.

How slopsquatting turns a hallucination into an attack

A nonexistent name isn't automatically dangerous. If you try to install it and the registry doesn't have it, the install fails.

The risk starts when someone registers that name first. Then the next developer who follows the AI's suggestion may end up installing the attacker's package instead of hitting a clean "package not found" error.

That's the slopsquatting play: identify plausible package names AI tools might invent or recommend, publish packages under those names, and wait. It's similar in shape to typosquatting, but here the "typo" source may be a confident-sounding model suggestion rather than a human spelling mistake.

Also, don't ignore what installation can do. Many package managers run build or setup steps, and a malicious dependency can try to access local files, credentials available to the process, or other resources the environment allows. The details depend on the package manager and your setup. The safe assumption isn't "every package is malicious." It's that an unverified name shouldn't be treated as safe just because an AI suggested it.

Why checking existence is a useful first filter

A real dependency review can include lots of things: reading source, checking maintenance history, pinning versions, and running vulnerability checks. Those are all useful - but they take time.

For a dependency list you just generated, registry existence is the quickest first test. If the name isn't there, stop and verify what you actually meant before installing anything. If it is there but it was published only days ago, treat that as a reason to dig deeper - not proof that it's malicious. A new package can be legitimate, but it has less history to lean on.

What phantom-deps Checks

phantom-deps is a small command-line scanner built for the narrow window right before installation. It checks dependency names against package registries and flags names that are missing or unusually new.

It can scan common dependency files, including:

  • requirements.txt
  • pyproject.toml
  • setup.cfg
  • package.json
  • Bare Python imports found in a project

For third-party names, it checks the relevant registry: PyPI for Python packages and npm for JavaScript packages. The scanner reports two kinds of results.

PHANTOM: no package found

A PHANTOM result means the referenced name doesn't exist in the registry that was checked. That's the most direct "this might be hallucinated" signal.

It can also happen for other reasons: a spelling mistake, an import-to-package mapping problem, a private dependency, or a registry mismatch. Either way, you shouldn't install based on that name until a human reviews what you intended.

And please don't "fix" it by guessing a similar package name and installing that. Find the intended library from a trusted source (official docs or a repository you already trust), then update the dependency list intentionally. A plausible alternative is not automatically the correct one.

NEW: published less than 30 days ago

A NEW result means the package exists, but it was first published fewer than 30 days ago. This is a warning flag, not a verdict.

The short timeline matters because new registrations have limited track record - and a name that was recently suggested or anticipated can be a target. Still, a recently published package might be legitimate: a new project, a new package name, or an internal workflow made public. The point is to look closer, not to automatically reject it. Check who maintains it, whether the project's official documentation points to the same registry entry, and whether the release history makes sense for your use case.

Designed to be lightweight

The project describes itself as having zero third-party dependencies. It uses Python's standard library and talks to the PyPI JSON API and the npm registry. It also caches registry results locally, so repeated checks don't re-download everything from scratch.

That simplicity is the point: there's no daemon, account, or SBOM pipeline required to do a quick pre-install check. But it also means it's not trying to be a full software composition analysis platform. Treat it as one early verification step, not a replacement for your normal dependency management and security work.

How to Use the Scanner in a Project

The workflow is simple: install phantom-deps, point it at your project or dependency files, review anything it flags, and only then proceed with installation. phantom-deps is available on PyPI and is MIT licensed.

Install it with:

pip install phantom-deps

Then scan a project directory:

phantom-deps ./my-ai-generated-project

You'll get output like:

PHANTOM  -  does not exist on the registry (1):

āœ— datavalidator-pro [pypi, from requirements.txt]

NEW - published recently, high risk (1):

! fastjson-utils (6d old) [pypi, from imports]

Your exact results will depend on what you scan. The useful part is the combination of status, registry, and where it came from - so you can track down the specific dependency declaration or import that needs attention.

Review findings before installing

When phantom-deps flags something, it helps to follow a small, consistent review loop:

  1. Confirm what the code actually needs. Figure out the intended functionality and whether the AI-generated import is necessary.
  2. Verify the package name independently. Use the library's official documentation or repository, not another generated suggestion.
  3. Check the registry and project history. For NEW, look at the publisher, links, release info, and whether a trusted source references it.
  4. Edit the dependency declaration. Fix or remove the name in your project file, then run the scan again.
  5. Only install once the dependency list makes sense. An existence check doesn't prove safety. Use your normal security controls too.

This avoids turning the scanner output into an automatic allow/deny switch. In real projects, automation is most helpful when it narrows the question to something a developer can actually answer.

Add it to CI or a pre-commit workflow

phantom-deps returns exit code 1 when it finds something. That makes it easy to use in automation, for example:

phantom-deps . || echo "unverified dependencies  -  review before installing"

This prints a reminder, but it doesn't necessarily stop the rest of your shell script. If you want flagged findings to block builds, configure CI to fail based on that exit code - don't accidentally swallow it with ||. If you prefer a review-only warning, make that behavior explicit so nobody assumes the pipeline enforced a real gate.

A practical rollout approach is: run the check on AI-generated code first, then decide whether it should be part of your broader dependency workflow. Blocking every newly published package can slow teams down - especially when they intentionally use fresh releases. Reporting the finding and requiring review can be a better starting policy while you learn which signals matter in your repositories.

Where This Check Fits - and Where It Does Not

Many dependency security tools focus on packages after they're already in a project: scanning lockfiles, tracking known vulnerabilities, or monitoring registry activity. Those checks matter. They just don't answer the immediate question that shows up right before installation: does this name even exist?

phantom-deps is aimed at that earlier moment. Its strongest use case is checking an AI-produced dependency file or import block before it touches your development environment. That's a useful addition because it adds a little friction before a potentially consequential action.

Import names are not always distribution names

For Python, there's an extra gotcha: the name you import in code isn't always the name of the package you install.

For example, bs4 is commonly provided by beautifulsoup4, PIL by Pillow, and cv2 by opencv-python.

phantom-deps uses best-effort mappings for common cases and verifies the mapped names against the registry. That helps with imports that are hard to match directly. But mappings aren't perfect: imports might come from a local module, a private package, or a distribution with a different name. When mapping is uncertain, it's still on you to do a manual check - not to assume the tool is right.

Registry checks depend on network access

phantom-deps needs network access to reach the registries. The project notes that it fails open on network errors: if a registry can't be reached, you'll get a note instead of a false PHANTOM finding.

That avoids confusing "the network is down" with "the package doesn't exist." But it also means a network error is not verification. If the registry couldn't be reached, treat the result as unresolved. If your team uses strict security gating, make sure you distinguish "scan completed" from "scan couldn't finish."

Existence is not trustworthiness

A real package can still be malicious, compromised, abandoned, or just a bad fit. A new package isn't automatically bad either.

So keep the labels in perspective:

  • A missing package means you should verify the name and intended dependency.
  • A recent package means you should apply extra scrutiny because history is thin.
  • An existing, older package still needs your normal checks.
  • A network error means the registry check didn't actually complete.

This is why a pre-install scanner complements - not replaces - lockfiles, code review, vulnerability monitoring, and controlled build environments. It closes one specific gap: installing a convincing name before confirming it's real.

Conclusion

AI-generated code can save time, but a believable dependency name isn't proof that the package exists - or that it's safe. The USENIX Security 2025 research reported that a substantial share of model-generated package references pointed to unpublished names, which gives attackers a reason to register those names in advance.

phantom-deps gives you a lightweight pre-install check for missing and very recently published packages. Use it to catch suspicious names, verify flagged dependencies directly, and keep your usual security controls in place. The next time an AI assistant hands you a dependency list, scan it before you install anything. Start with the phantom-deps project and decide where this check fits in your workflow.

Frequently Asked Questions

Slopsquatting is the practice of registering package names that AI systems may hallucinate or recommend incorrectly. A developer who later installs one of those names could receive an attacker-controlled package instead of an installation error.
No. It checks whether a name exists in the relevant registry and flags packages published within the last 30 days. Existence and age are useful signals, but they do not establish that a package is benign, well maintained, or appropriate for your project.
It scans requirements.txt, pyproject.toml, setup.cfg, package.json, and bare Python imports. It checks Python package names against PyPI and JavaScript package names against npm, according to the project description.
Treat the result as unverified. The tool reports network problems as notes rather than falsely labelling a package as nonexistent. Restore registry access and rerun the check, or verify the dependency through a trusted source before installing it.
Yes. The command exits with status 1 when it finds a flagged dependency, so CI or a pre-commit hook can act on that result. Decide whether findings should block the workflow or prompt a review, and ensure network errors are not mistaken for a completed verification.

Related articles