--- name: dep-verify-guard description: Blocks hallucinated, typosquatted/slopsquatted, and unnecessary dependencies from being installed by verifying each new package against the real registry (npm/PyPI/crates) before it's added. Best used reactively before adding, importing, or installing any dependency. Use when the user says "install X", "add a package for", "npm/pip/cargo add", "import", or when a coding agent introduces a new third-party import. DO NOT USE for secret exposure (use no-secret-leak-guard) or general diff review (use clean-diff-guard); this guard is specifically about dependency existence, typosquatting, and necessity. --- # dep-verify-guard Never install a package on faith. LLMs predictably hallucinate plausible-sounding package names, and attackers pre-register those exact names on public registries so the hallucination becomes a working, malicious install the moment an agent runs `npm install `. This guard makes "does this package actually exist, and do we actually need it" a checked step, not an assumption. Research on this failure mode (CSA, Unit42, and related slopsquatting studies) found that LLM code generation hallucinates non-existent package names in a meaningful fraction of dependency-adding requests, and that a large fraction recur (reported in 2025–2026 slopsquatting research) across repeated runs of the same prompt — stable enough for an attacker to pre-register the exact name and wait. `react-codeshift` is a plausible example of the pattern: a name an LLM could plausibly produce by conflating two real packages (`jscodeshift` + `react-codemod`), but it does not exist as a real published package. This guard exists to catch that pattern before `npm install` runs, not after. ## When to use — three modes - **Guard-pass (default).** Right before running `npm install` / `pip install` / `cargo add` / `yarn add` / `pnpm add`, or before writing an `import`/`require` statement for a package not already in the manifest/lockfile: verify the package per the Procedure below. This is the mode that fires on trigger phrases like "install X," "add a package for," "npm/pip/cargo add," or "import." - **Live.** While actively writing code and reaching for a third-party helper mid-task (e.g., typing `import { chunk } from 'lodash.chunk'`): pause at the import line itself, not at a later review pass. Verify the name is real and actually needed before the line is finalized, the same way you'd check a function signature before calling it. - **Review.** When asked to review a diff, PR, or lockfile change that adds dependencies: treat every new entry in `package.json`/`requirements.txt`/`Cargo.toml` and its corresponding lockfile as something to verify, not something to wave through because it's already there. A dependency added by a previous agent turn or a teammate gets the same scrutiny as one you're about to add yourself. ## What this guard blocks 1. **Unverified existence.** For EVERY new import/package, verify it exists on the real registry (npm, PyPI, crates.io, etc.) using available tools — a registry lookup, the package manager's own `search`/`info`/`view` command, or a web fetch of the registry's public API. Never assume a plausible-sounding name is real because it "sounds like" a package that should exist. See `references/registry-verification.md` for the per-ecosystem commands. 2. **Typosquat / conflation near a popular package.** Check whether the requested name is a near-miss of, or a plausible mashup of, an established popular package. List the closest real ones by name when flagging this — e.g. `react-codeshift` → the real packages are `jscodeshift` and `react-codemod`; `python-dateutil` typo'd as `python-datetuil` → the real package is `python-dateutil`. See `references/slopsquat-checklist.md` for the common hallucinated-name shapes (conflation, pluralization drift, scope-dropping, version-suffix guessing). 3. **Suspicious-new or low-signal packages.** Flag packages that are brand-new (registered days to a few weeks ago), have zero or near-zero weekly downloads, have a single maintainer with no other published packages, or have had no release in years while claiming to solve an actively-maintained problem — for human confirmation before installing. A name existing on the registry is necessary but not sufficient; a squat is also "real" the moment it's registered. 4. **Unnecessary additions.** Before adding any package, check whether the standard library or an already-installed dependency already covers the need. Do not add a package the task didn't actually require — every added dependency is additional supply-chain surface, install-time code execution risk, and maintenance burden, regardless of how small it is. 5. **Unpinned / unrecorded resolution.** Once a package is verified and genuinely needed, record the exact resolved version (not a loose `^`/`*` range invented from memory) in the manifest and confirm it lands correctly in the lockfile. Note explicitly that most package managers run arbitrary install-time scripts (`postinstall`, build hooks) for every transitive dependency — a verified top-level package can still pull in an unverified, unreviewed dependency tree. 6. **Can't-verify means ask, not install.** If the available tools cannot confirm a package's existence (no network access, registry lookup fails, ambiguous name with no single best match), say so explicitly and ask the user before installing. Do not fall back to "it's probably fine" — the entire point of this guard is that "probably fine" is exactly how slopsquats get installed. ## Procedure — guard-pass steps 1. **Enumerate the new dependencies.** Diff the manifest (`package.json` dependencies/devDependencies, `requirements.txt`/`pyproject.toml`, `Cargo.toml`) and/or lockfile against what was there before this change. List every package that is new, not already present. 2. **Verify each one exists**, using the ecosystem's own tooling (`npm view `, `pip index versions ` / PyPI JSON API, `cargo search `) per `references/registry-verification.md`. Record what came back: exists / does not exist / ambiguous. 3. **Check for typosquat/conflation** against well-known packages solving the same stated problem, using `references/slopsquat-checklist.md`'s heuristics. If the name is a near-miss or a mashup, name the real package(s) it's most likely confused with. 4. **Check age, downloads, and maintenance signal** for anything that exists but looks new or thin. Note the registered date, weekly download count (if available), and last-release date in the report. 5. **Ask "did the task actually need this?"** Check the standard library and the existing dependency tree first. If an existing capability covers it, recommend that instead and do not add the package. 6. **Report per package**: exists (Y/N) · age/downloads/maintenance signal (if thin, flagged) · typosquat risk (named alternatives if any) · necessity call (needed / stdlib-or-existing-dep-covers-it) · resolved version to pin. 7. **If everything checks out**, proceed with the install/import and record the resolved version. If anything is unverified, hallucinated, squatted, thin, or unnecessary, stop and surface it before installing — do not install first and mention concerns after. 8. **Emit the guard footer** (see Output) as the last line of the response. ## Output Emit this verbatim as the last line of any response where a dependency was added, considered, or reviewed: ``` proofguard:dep-verify-guard — · Triggered: · Fixed: · Verified: · Remaining gap: ``` - `PASS` — every new dependency was confirmed to exist, isn't a typosquat/conflation of a real package, isn't suspiciously new/thin without disclosure, and is actually needed (stdlib/existing deps don't already cover it). - `FIX-REQUIRED` — a hallucinated, typosquatted, unverifiable, or unnecessary package was about to be installed and has not yet been resolved (swapped for the real package, dropped in favor of stdlib, or held for human confirmation). - `WAIVED(reason)` — the user, as the actual principal, explicitly accepted a flagged risk (e.g. "yes, install the brand-new package anyway, I trust the author") with a stated reason. ## References - `references/slopsquat-checklist.md` — the slopsquatting threat model, the `react-codeshift` case in detail, and the common shapes hallucinated package names take (conflation, pluralization drift, scope-dropping, plausible-suffix guessing). - `references/registry-verification.md` — exact per-ecosystem commands for verifying existence, age, and download/maintenance signal (npm, PyPI, crates.io), plus the stdlib-first rule. ## What this guard does NOT do It is not a full SCA (software composition analysis) or vulnerability scanner — it does not check known-CVE databases, license compatibility, or dependency-tree-wide risk scoring. For that, recommend `npm audit`, `osv-scanner`, or Socket as a follow-up. This guard targets the failure mode vulnerability databases structurally cannot catch: a hallucinated or freshly-squatted package name has no CVE history yet, because nothing has been reported against it — the risk is entirely in whether the name is real, correctly typed, and actually needed, which is exactly the window before install where vuln scanners have nothing to say.