pkgguard / pre-install security gate

Stop the package your agent invented.

pkgguard checks npm, PyPI and crates.io names before your package manager runs them, and answers ALLOW, REVIEW or BLOCK with the reasons. It catches the names AI coding agents hallucinate, the slopsquats registered to exploit them, and typosquats that spelling checks miss.

Free and open source · CLI · HTTP API · MCP server · GitHub Action · Apache 2.0 · no account, no key

Install

One command. Nothing to sign up for.

Python 3.9 or newer. It runs where your agent or CI runs, and asks the public registries directly.

pip install "git+https://github.com/rxslice/pkgguard-API.git"
pkgguard check -e npm react-codeshift lodash

BLOCK  react-codeshift  [npm]  risk=100
       - Name appears on the known-hallucination corpus.
       - Name appears to blend 2 real packages (jscodeshift, react) into a
         combination that does not exist.
       - Only a single published version, with no release history.
       - Low adoption: 22 downloads in the last month.
       - No source repository linked in the registry metadata.
ALLOW  lodash  [npm]  risk=0
       - Established package with no risk signals.

2 checked | 1 blocked | 0 review | 1 allowed

Install it from GitHub, not from PyPI. pkgguard is not published on PyPI and the name there is unclaimed. An unclaimed name that people are told to install is exactly what slopsquatting exploits, so never run a bare pip install pkgguard. Pin a release by adding @v0.1.0 to the URL.

Why this exists

AI can invent a package that sounds real.

Slopsquatting is the supply-chain attack that follows: an attacker registers a name an AI is likely to hallucinate, and the install command brings it into your build. Autonomous agents now run those commands themselves, so the human who used to glance at them is gone. Typosquat scanners miss the common case, because an invented name that blends two real ones is not a misspelling of either.

01 / Verify identity

Does the name exist in its registry? How old is it, how many versions, how many downloads, is there a source repository?

02 / Score risk

Combine age, documented hallucinations, conflation and typosquat signals into one decision, with every reason listed.

03 / Gate the install

Enforce one boolean, safe_to_execute, in an agent, a CI job, an MCP host or an install wrapper. It fails closed.

Accuracy

Measured against real registries.

Benchmarked on live registry data, not synthetic fixtures, and reproducible with one script in the repository.

1.0%

false BLOCKs on 200 real npm packages outside the popularity corpus

96.0%

of those legitimate packages ALLOWed outright, with 3.0% sent to REVIEW for a person to decide

7/7

real threats caught: slopsquats, conflations and typosquats, including react-codeshift and unused-imports

The first version of the conflation check scored 0% false positives, and that test was worthless: it ran on packages the popularity corpus short-circuits. Run honestly on 800 packages outside it, the same check flagged 62.5% of legitimate names. Two changes brought it to 1.0%: conflation can no longer block on its own, only alongside weak reputation, and typosquats are measured by a name's share of its namesake's downloads rather than by spelling.

python scripts/benchmark.py --sample 200
Use it

Wherever the install happens.

In a terminal or script

Check names, check a command an agent wrote, or gate a whole manifest. Exits 1 on BLOCK.

pkgguard check -e pypi requests-oauth2-helper
echo "npm install react-codeshift" | pkgguard scan-command
pkgguard scan-manifest requirements.txt

In front of an agent's install

Wrap the real command. It runs unchanged only when pkgguard allows it.

pkgguard-gate -- npm install react-codeshift
pkgguard authorize "uv add requests"

Understands npm, yarn, pnpm, bun, pip, uv, poetry and cargo. Chaining, pipes, redirection and shapes it does not recognise go to REVIEW instead of being half-parsed.

As an MCP tool

One tool, authorize_install_command, over stdio for any MCP host. It returns the decision, safe_to_execute, the packages and the full assessment.

pkgguard-mcp

In GitHub Actions

Fails the build on BLOCK and REVIEW and publishes findings to Code Scanning as SARIF.

- uses: rxslice/pkgguard-API/.github/actions/scan@main
  with:
    manifest: package.json

As your own HTTP API

The same checks behind two endpoints, served by you, for a fleet of agents or a platform. There is no hosted pkgguard to sign up for: you run it, so your install decisions never leave your infrastructure.

pip install "pkgguard[api] @ git+https://github.com/rxslice/pkgguard-API.git"
uvicorn pkgguard.api:app --port 8000

curl -X POST http://127.0.0.1:8000/v1/agent/authorize \
  -H "Content-Type: application/json" \
  -d '{"command":"npm install react-codeshift lodash"}'

curl -X POST http://127.0.0.1:8000/v1/verify \
  -H "Content-Type: application/json" \
  -d '{"names":["react-codeshift","express"],"ecosystem":"npm"}'
→ { "blocked": 1, "allowed": 1, "safe_to_proceed": false, ... }

Interactive documentation is served at /docs. A single-name check is GET /v1/verify/npm/express.

Scoring

Every point is explained.

BLOCK at 60 or more, REVIEW at 25 or more, otherwise ALLOW. A registry that cannot be reached never produces ALLOW: it produces REVIEW with the error shown.

SignalPointsWhy
Package does not exist+70An AI suggested a name that is not real
On the known-hallucination corpus+60Documented in public research
Confirmed typosquat+60Close spelling and under 1% of the target's downloads
Conflation, with weak reputation only+30Cannot reach BLOCK alone, by design
30 days old or less+30
Typosquat that cannot be resolved+30No download data, so it fails toward caution
120 days old or less+15
Single published version+15
Under 1,000 monthly downloads+15
No source repository+10
Limitations

Read these before relying on it.

  • Conflation cannot tell a hallucination from a legitimate new package that blends common words. That is why it only counts alongside weak reputation.
  • The known-hallucination corpus is small on purpose. It holds only names with a citable public source, because a guessed entry produces a confident, wrong BLOCK.
  • PyPI download statistics are supplemental. When pypistats.org is slow or down, PyPI decisions fall back to reputation signals.
  • It does not read package contents. It is one layer of defense, not a supply-chain security program.

For a hosted check that also carries a growing record of the names models keep inventing, see HALLUX, which folds pkgguard in.

Answers for people and agents

Questions worth asking.

What does pkgguard check?

Whether an npm, PyPI or crates.io name exists, how old it is, how many versions and downloads it has, whether it has a source repository, whether it is a documented hallucination, whether it blends two real package names, and whether it is a typosquat measured by its share of the real package's downloads. It combines those into ALLOW, REVIEW or BLOCK and lists the reasons.

Does it scan package contents for malware?

No. It protects the decision before anything is installed. Pair it with a content or runtime scanner for defense in depth.

Is it free?

Yes. Apache 2.0, free for commercial use, with no account, no API key and no paid data feed.

Why install it from GitHub rather than PyPI?

It is not published on PyPI, and the name there is unclaimed. Installing it from its repository means you get this code, not whatever a stranger might register under the name.

How do I connect it to an AI agent?

Use the MCP server, the install wrapper, your own HTTP endpoint or the GitHub Action. Each returns an explicit decision and a safe_to_execute boolean, and each fails closed.

Will it flag my legitimate new package?

A brand-new package with one version and few downloads will usually get REVIEW, and BLOCK only if other signals pile up. Teams that want a human approval step instead of a hard stop for new packages can set --new-package-policy review; documented hallucinations and confirmed typosquats stay blocked.