PACKAGE HALLUCINATION SCANNER

AI coding tools invent package names that don't exist. Attackers publish those invented names with malware inside. This scanner catches the switch before you `npm install` something dangerous.

SCAN YOUR DEPENDENCIES NOW

Enter your repo URL or deployed app URL — we resolve the manifest (package.json, requirements.txt, pyproject.toml, Gemfile, go.mod, Cargo.toml) and check every dep against the registry.

The Slopsquatting Problem

AI coding tools frequently suggest package names that don’t exist — a side effect of how they generate plausible-looking imports. When enough developers encounter the same hallucinated name, attackers register it on npm with malware inside. Every subsequent npm install is a potential compromise.

This is slopsquatting — typosquatting’s AI-era evolution. It’s already hit thousands of real packages across npm and PyPI. The novel part: the attacker doesn’t need to typo-bait you. The model already proposed the wrong name; the attacker just races to register it before the legitimate maintainer notices (and many never will, because the name was never legitimate to begin with).

Why hallucinated names cluster

Models hallucinate package names in patterns, not at random:

  • Plausible compositionreact-router-dom is real, so the model proposes react-router-native-dom or react-router-typed. Sounds right, doesn’t exist (or didn’t, until somebody registered it).
  • Cross-ecosystem confusion — Python’s requests becomes node-requests on npm. Java’s Jackson becomes jackson-js.
  • Version-suffix inventionlodash becomes lodash-2 or lodash-modern to look “newer”.
  • Scope swap@aws-sdk/client-s3 becomes aws-sdk-s3 or @aws/sdk-s3. Same words, wrong scope, wrong package.
  • Plural / singular swapcookies instead of cookie, validators instead of validator.

The same hallucination shows up across many users because the model’s prior is the same. That convergence is what makes the attack economical: register one name, catch hundreds of installs.

What the Scanner Checks

NON-EXISTENT PACKAGES

Imports that point to names never published to the registry.

RECENTLY REGISTERED

Packages created <30 days ago with low download counts — typical slopsquat profile.

TYPOSQUATS

Names one character off from popular packages (reactt, expressjs, lodasch).

SUSPICIOUS SCRIPTS

Packages with post-install hooks that fetch remote code or write outside node_modules.

SCOPE / NAMESPACE DRIFT

Unscoped packages mimicking scoped originals (aws-sdk-s3 vs @aws-sdk/client-s3).

OWNER CHANGE

Recent maintainer transfer on a popular package — common precursor to a malicious version bump.

BINARIES IN TARBALL

Native .node or .so files inside a package whose source code is pure JS — runs unsigned binary code on install.

OBFUSCATED SOURCE

Heavily minified or base64-encoded payloads inside an otherwise readable package — common malware tactic.

How to Use

  1. Paste the contents of your package.json, requirements.txt, pyproject.toml, Gemfile, go.mod, or Cargo.toml
  2. The scanner checks each dependency against the relevant registry
  3. Flagged dependencies are ranked by risk — with alternative packages suggested

The check is read-only: nothing is installed, nothing executes.

Anatomy of a real slopsquat attack

The pattern from the wild reads like this:

  1. A developer asks an AI assistant to add HTTP retry logic. The model emits import retry from 'http-easy-retry'; — a plausible name that does not exist on npm.
  2. An attacker (running their own scraper that watches public repos and AI assistant logs) sees http-easy-retry referenced multiple times within a day. They publish version 1.0.0 to npm with a benign index.js and a postinstall hook.
  3. The hook runs on every npm install. It downloads a payload from attacker.example/p.sh, exfiltrates ~/.aws/credentials, ~/.npmrc (which contains your npm publish token), ~/.env, and any .git configs.
  4. Now the attacker has your AWS keys and your npm publish credentials. They can publish malicious versions of any package you maintain — supply-chain compromise of every downstream user.

There’s nothing exotic about step 2. The npm registry adds tens of thousands of new packages per month; nobody is reviewing them.

Ecosystem-specific guidance

Ecosystem Manifest Verify install scripts Lock file
npm package.json --ignore-scripts in CI package-lock.json (committed)
Yarn package.json enableScripts: false in .yarnrc.yml yarn.lock (committed)
pnpm package.json --ignore-scripts or allowlist via onlyBuiltDependencies pnpm-lock.yaml (committed)
PyPI (pip) requirements.txt / pyproject.toml pip install --no-build-isolation won’t help; review wheels requirements.txt with hashes via --require-hashes
Cargo Cargo.toml cargo install runs build scripts; review build.rs Cargo.lock (committed)
Go go.mod No install scripts (sandboxed) go.sum (committed)
Ruby Gemfile gem install runs extconf.rb; review native gems Gemfile.lock (committed)

Go is the safest by design — modules don’t have install hooks. npm is the most exposed.

Fix Recipes

  • Non-existent package: Check the AI’s suggestion against the real registry. Usually the correct name is 1 character off or has a different scope.
  • Suspicious new package: Pin to a known-good version on a trusted fork, or remove the dependency entirely.
  • Typosquat: Replace with the legitimate package name. Add to your CI block-list.
  • Post-install hooks: Use --ignore-scripts in CI, review each hook before allowing in production.

npm safe-install pattern:

# CI: install with no scripts, then run only the scripts you've vetted
npm ci --ignore-scripts
npm rebuild --ignore-scripts=false <only the native deps you trust>

pip with hash pinning:

# requirements.txt
requests==2.32.3 --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760

A hash mismatch on the next install means the package contents changed — a strong signal of a malicious republish.

Block install on unknown deps in CI:

# Pseudo-CI step
- name: Verify deps against allowlist
  run: |
    diff <(jq -r '.dependencies | keys[]' package.json | sort) deps-allowlist.txt

If a dep was added that isn’t in deps-allowlist.txt, the build fails — every new package gets a human review.

What this scanner does NOT flag

  • Real, popular packages with newly-disclosed CVEs. That’s a job for npm audit / pip-audit / osv-scanner. Different problem; we focus on non-existence and attribution signals, not vulnerabilities in legitimate code.
  • Trojan-source-style hidden Unicode in source code. Out of scope at the manifest level.
  • Packages that became malicious after you locked them. A lockfile pinned to a known-good version stays good unless you re-resolve. That’s the value of the lockfile — keep it committed.
  • Dependency confusion via private registries. If your CI is misconfigured to fall back to public npm for a private scope, public attackers can publish a higher-version package to the public registry and get pulled in. Check your .npmrc registry and scope mappings — separate concern.
  • Compromise of the registry itself. Out of scope of any manifest scanner.

COMMON QUESTIONS

01
What is a hallucinated package?
An AI-generated import statement that names a package that doesn't exist on npm, PyPI, or other registries — or one that *now* exists because an attacker registered it to catch unsuspecting developers.
Q&A
02
Why is this dangerous?
'Slopsquatting' attacks: attackers monitor AI outputs, register commonly-hallucinated names with malware, and wait. Your `npm install` pulls in their payload. This has already happened with thousands of packages.
Q&A
03
What ecosystems are supported?
npm (package.json), PyPI (requirements.txt, pyproject.toml), Ruby (Gemfile), Go (go.mod), and Cargo (Cargo.toml). Paste in any of these and we check every dependency.
Q&A

RUN THE FULL SUPPLY-CHAIN AUDIT

Beyond hallucinations: known CVEs, typosquats, abandoned packages, and risky post-install scripts.

RUN FULL SCAN