2025 research confirmed LLMs hallucinate package names in roughly 19.7% of coding suggestions, and attackers registered malicious packages matching the most frequent hallucinations. A production startup was compromised in Jan 2026 when a developer ran npm install on a Claude-suggested package that did not exist until an attacker registered it weeks earlier. This tutorial builds a verification step that runs before any LLM-suggested install.
Prerequisites
- Node.js 20+
- A Scavio API key (free 500 credits)
- Access to npm CLI
Walkthrough
Step 1: Install the Scavio client
Add Scavio to your tooling workspace.
npm install scavioStep 2: Write the verification function
The verifier checks three signals: npm registry, Google SERP, and Reddit discussion.
import { Scavio } from 'scavio';
import { execSync } from 'child_process';
const scavio = new Scavio({ apiKey: process.env.SCAVIO_API_KEY });
export async function verifyPackage(name: string) {
const registryExists = await fetch(`https://registry.npmjs.org/${name}`).then(r => r.ok);
if (!registryExists) return { safe: false, reason: 'Does not exist on npm' };
const serp = await scavio.search({ query: `npm "${name}"` });
const hasDocs = serp.organic_results?.some((r: any) => r.link.includes('npmjs.com') || r.link.includes('github.com'));
const reddit = await scavio.search({ platform: 'reddit', query: name });
const mentions = reddit.organic_results?.length || 0;
return { safe: hasDocs && mentions > 0, hasDocs, mentions };
}Step 3: Wrap npm install
Block installs that fail verification.
import { verifyPackage } from './verify';
const pkg = process.argv[2];
const result = await verifyPackage(pkg);
if (!result.safe) {
console.error(`BLOCKED: ${pkg} failed verification`, result);
process.exit(1);
}
execSync(`npm install ${pkg}`, { stdio: 'inherit' });Step 4: Wire it into your LLM workflow
Claude Code, Cursor, or any agent that suggests installs should run verify before executing.
// In your agent's pre-install hook:
const verified = await verifyPackage(suggestedPackage);
if (!verified.safe) throw new Error('Blocked hallucinated package');Step 5: Test with a known hallucination
Try a plausible-but-fake package name to confirm the verifier catches it.
node install-safe.js ultra-fast-json-parser-pro-2026
# BLOCKED: failed verificationPython Example
import os, requests
from scavio import Scavio
scavio = Scavio(api_key=os.environ['SCAVIO_API_KEY'])
def verify_package(name):
if not requests.get(f'https://pypi.org/pypi/{name}/json').ok:
return {'safe': False, 'reason': 'Not on PyPI'}
serp = scavio.search(query=f'pypi "{name}"')
has_docs = any('pypi.org' in r['link'] or 'github.com' in r['link'] for r in serp['organic_results'])
reddit = scavio.search(platform='reddit', query=name)
return {'safe': has_docs and len(reddit['organic_results']) > 0}JavaScript Example
import { Scavio } from 'scavio';
const scavio = new Scavio({ apiKey: process.env.SCAVIO_API_KEY });
export async function verifyPackage(name) {
const exists = await fetch(`https://registry.npmjs.org/${name}`).then(r => r.ok);
if (!exists) return { safe: false };
const serp = await scavio.search({ query: `npm "${name}"` });
return { safe: serp.organic_results?.length > 0 };
}Expected Output
Hallucinated names are blocked before install. Real packages pass verification in under 2 seconds (npm lookup + 2 Scavio calls at ~60 credits total).