agentgate deps
Detect hallucinated and typosquatted dependencies before they are installed.
agentgate deps [target] [options]LLMs hallucinate package names — a USENIX Security 2025 study found 19.7% of
AI package recommendations reference packages that don’t exist. Attackers
register those names on npm and PyPI (“slopsquatting”), so a copy-pasted
npm install or pip install pulls attacker code. agentgate deps intercepts
this before installation.
What it checks
Section titled “What it checks”- Collects dependency names from
package.json(all dependency sections),requirements*.txt,pyproject.toml(PEP 621 + Poetry), and bare import specifiers in.js/.ts/.pysource files (imports already declared in a manifest, Node builtins, and the Python stdlib are excluded). - Verifies existence against the live npm and PyPI registries. A package
that doesn’t exist is a critical finding (
AG-DP-001) — it’s likely hallucinated and an attacker can register it. First-party modules found in the scanned tree and imports inside comments/docstrings are excluded; a nonexistent name imported only under a test/example path is downgraded tolow(usually a runtime-generated or sample module). - Risk-scores existing packages from registry metadata: name similarity to
popular packages (
AG-DP-002, typosquats), young/near-zero-download packages (AG-DP-003), npm install scripts combined with other risk signals (AG-DP-004), and weak metadata like missing repository/license (AG-DP-005). Dependencies declared with a mutable remote specifier — a git ref that isn’t a full commit SHA (medium) or a non-registry archive URL (high) — are flagged asAG-DP-007(works offline too). This covers npmpackage.jsongit/URL specifiers and Python PEP 508 direct references (name @ git+https://…/name @ https://…) inrequirements*.txtandpyproject.toml. - Checks known-malware advisories against OSV.dev
(which aggregates the GitHub Advisory Database, PyPI, and the OSV
malicious-packages project). A dependency with a
MAL-*advisory is a critical finding (AG-DP-006) linking to the advisory. When the advisory only covers specific compromised releases (e.g. the 2025debug/chalkincident), the resolved version — fromnode_modules, or a lockfile (package-lock.json,pnpm-lock.yaml,yarn.lockv1,poetry.lock,uv.lock; best-effort parsing) — is compared: unaffected =low, affected =critical, unresolvable =high(“verify your lockfile”). Version-range CVEs are out of scope; use a dependency vulnerability scanner (osv-scanner,npm audit) alongside. Skipped with a warning when OSV.dev is unreachable or in--offlinemode.
Options
Section titled “Options”| Flag | Default | Description |
|---|---|---|
-f, --format <format> |
table |
table, json, or sarif. |
-o, --output <file> |
stdout | Write the report to a file. |
--fail-on <severity> |
high |
Exit 1 when findings reach this severity — the CI gate. Use never to report without gating. |
--ignore <globs...> |
— | Exclude paths (e.g. vendor/**). |
--offline |
off | Skip registry lookups; name-shape (typosquat) checks only. |
--no-imports |
off | Check manifests only; skip source import extraction. |
-t, --timeout <ms> |
10000 |
Per-request registry timeout. |
--concurrency <n> |
8 |
Max concurrent registry lookups. |
CI usage
Section titled “CI usage” with: command: depsOr as a pre-commit hook (id: agentgate-deps), which runs whenever a
dependency manifest changes.
Honest boundaries
Section titled “Honest boundaries”This is a heuristic risk gate, not a proof of safety:
- A clean result does not guarantee a package is safe; a flagged result is a signal to review, not proof of malice.
- PyPI download counts are not available via the JSON API, so PyPI scoring relies on age, versions, and metadata quality.
- Source import extraction is regex-based, not a full parser; Python
import-name → PyPI-name mapping is best-effort (e.g.
PILvspillow). - Registry lookups need network access; failures degrade to
infofindings. Use--offlinewhere CI has no egress.