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 composition —
react-router-domis real, so the model proposesreact-router-native-domorreact-router-typed. Sounds right, doesn’t exist (or didn’t, until somebody registered it). - Cross-ecosystem confusion — Python’s
requestsbecomesnode-requestson npm. Java’s Jackson becomesjackson-js. - Version-suffix invention —
lodashbecomeslodash-2orlodash-modernto look “newer”. - Scope swap —
@aws-sdk/client-s3becomesaws-sdk-s3or@aws/sdk-s3. Same words, wrong scope, wrong package. - Plural / singular swap —
cookiesinstead ofcookie,validatorsinstead ofvalidator.
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
- Paste the contents of your
package.json,requirements.txt,pyproject.toml,Gemfile,go.mod, orCargo.toml - The scanner checks each dependency against the relevant registry
- 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:
- 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. - An attacker (running their own scraper that watches public repos and AI assistant logs) sees
http-easy-retryreferenced multiple times within a day. They publish version1.0.0to npm with a benignindex.jsand apostinstallhook. - The hook runs on every
npm install. It downloads a payload fromattacker.example/p.sh, exfiltrates~/.aws/credentials,~/.npmrc(which contains your npm publish token),~/.env, and any.gitconfigs. - 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-scriptsin 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
.npmrcregistryand scope mappings — separate concern. - Compromise of the registry itself. Out of scope of any manifest scanner.
Related tools and guides
- Node.js Security Scanner — pair with this to harden the runtime your installed deps run inside.
- Vibe Code Scanner — full app audit, ties manifest findings to runtime exposure.
- Vibe Coding Security Risks — broader picture of AI-introduced vulnerabilities.
COMMON QUESTIONS
RUN THE FULL SUPPLY-CHAIN AUDIT
Beyond hallucinations: known CVEs, typosquats, abandoned packages, and risky post-install scripts.