
Research
/Security News
737 Chrome VPN Extensions Linked to Brand Impersonation and Browser Traffic Redirection
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.
slopgate-cli
Advanced tools
Install-gate hook that blocks slopsquatted / hallucinated npm packages before an AI coding agent installs them.
A hook that sits in front of your AI coding agent's npm installs and stops slopsquatted or hallucinated packages before they're ever fetched.
A supply-chain scanner tells you a package was bad after it's in your
node_modules. slopgate refuses to fetch a package that shouldn't exist in the first place — at the moment your agent typesnpm install.
LLM coding agents confidently invent package names that don't exist (gpt-commit-assistant, ai-code-reviewer-toolkit). Attackers register those hallucinated names and wait — slopsquatting. slopgate does exactly one thing that a supply-chain scanner like pkgxray doesn't: npm registry existence + freshness checking — is this package name real, and if so, is it suspiciously new / low-download in the shape of a name that was just squatted. For everything else (OSV, static heuristics, prompt-injection detection) it shells out to pkgxray and folds its verdict in. It never reimplements that analysis.
It reuses hookshot (imported as a Go library) so a single binary hooks Claude Code, Codex, Cursor, Windsurf Cascade, and Factory Droid from one unified handler.
slopgate is a single pure-Go binary.
# npm — ships prebuilt binaries for darwin/linux on arm64/amd64, no toolchain
npm install -g slopgate-cli
# from source (needs Go 1.21+ and the hookshot sibling repo checked out beside it)
git clone https://github.com/adamsjack711-ux/slopgate
git clone https://github.com/adamsjack711-ux/hookshot # replace target
cd slopgate && make install # builds → /usr/local/bin
go install …@latestisn't available yet: the build depends on a fork of hookshot via a localreplacedirective, so hookshot must sit beside slopgate. That goes away once hookshot is a tagged module.
Wire it into Claude Code (settings.json; the same binary serves the other agents via their own hook command names):
"PreToolUse": [{ "matcher": "Bash",
"hooks": [{ "type": "command",
"command": "/abs/path/to/slopgate claude-pre-tool-use" }] }]
For each npm package a command would fetch, three checks run cheapest-first, short-circuiting where they can:
GET registry.npmjs.org/<name>. A 404 is a hard stop: the
package doesn't exist. This is its own outcome (nonexistent), distinct from
a verdict, and it always denies.freshnessAgeDays and weekly
downloads < minWeeklyDownloads. Eligible on its own → at least review.pkgxray guard npm:<name>@<version> --format json, parsed
for its decision and cited report.findings.The results fold into one verdict using pkgxray's scheme — allow / review /
block — worst wins. The policy then maps that to a hook action.
| verdict | strict | balanced (default) | permissive |
|---|---|---|---|
allow | allow | allow | allow |
review | deny | ask | allow (warn) |
block | deny | deny | deny |
nonexistent | deny | deny | deny |
(npx / npm exec runners execute package code immediately, so a review that
would be allowed under permissive is hardened to ask.)
If pkgxray isn't on PATH, slopgate fails loudly and closed with install
instructions — never a cryptic subprocess error mid-install.
Before judging anything, slopgate has to find the packages a command would
fetch. It recognizes npm install|i|add, npm ci, npm exec, and npx, and:
NODE_ENV=production npm i x, sudo npm i x, and env FOO=bar npm i x are
still seen as npm installs rather than waved through as unrecognized shapes.npm install / npm ci — which names no packages — by
reading the direct dependencies from package.json in the agent's working
directory and gating each by name. This catches the common path where an agent
writes a hallucinated dependency into the manifest and then runs a plain
npm install. When the manifest can't be read, the install is held for
review instead of allowed. Only direct deps are read, and non-registry
deps (git:/file:/workspace:/url/alias) are skipped so a legitimate
non-registry dependency isn't false-denied.Packages are evaluated concurrently (bounded), so a manifest that fans out to many dependencies doesn't stall the install serially.
slopgate preflight # is pkgxray resolvable?
slopgate check express # evaluate a name or command, print JSON evidence
slopgate check 'npm i left-pad@1.3.0'
check prints the full evidence report to stdout and exits with pkgxray's
convention: 0 allow · 2 block/nonexistent · 3 review.
A single JSON file (~/.config/slopgate/config.json, or point at one with
SLOPGATE_CONFIG). Omitted fields keep their defaults; unknown keys are
rejected so a typo is caught. See config.example.json.
| field | default | meaning |
|---|---|---|
freshnessAgeDays | 30 | flag packages first-published younger than this (0 disables) |
minWeeklyDownloads | 100 | flag packages below this weekly-download count (0 disables) |
policy | balanced | strict | balanced | permissive (how review maps to an action) |
pkgxrayBin | pkgxray | path/name of the pkgxray executable |
skipPkgxray | false | run existence + freshness only; skip the pkgxray subprocess (and its preflight) |
skipPkgxray: true turns slopgate into a pure existence/freshness pre-check —
use it when a separate pkgxray gate (e.g. the pkgxray-guard hook) already runs,
so npm installs aren't guarded twice.
Environment:
SLOPGATE_DISABLE=1 — bypass slopgate entirely (operator kill switch)SLOPGATE_LOG — evidence log sink: stderr, or a file path (default: off).
Hooks are quiet by default; the agent sees only the decision reason.One binary, one OnBeforeExecution handler, five agents — each with its own hook
command name. All verified against a hallucinated install:
| Agent | Hook command | block / deny surfaces as | review (ask) surfaces as |
|---|---|---|---|
| Claude Code | claude-pre-tool-use | permissionDecision: deny (stdout JSON) | approval prompt |
| OpenAI Codex | codex-pre-tool-use | permissionDecision: deny | blocked (Codex doesn't enforce ask) |
| Cursor | cursor-before-shell | permission: deny (stdout JSON) | approval prompt |
| Factory Droid | droid-pre-tool-use | exit 2 + stderr reason | blocked (no ask path) |
| Windsurf Cascade | cascade-pre-run-command | exit 2 + stderr reason | blocked (ask not wired) |
An ask never fails open. On agents without an approval prompt
(Codex/Droid/Cascade), hookshot enforces a review-tier ask as a hard block —
so under balanced policy those agents behave like strict for the review tier
(safe, just no prompt). slopgate's deny/ask/allow → hook-decision mapping is
pinned by a test so a review can never silently become an allow.
The decisions worth knowing, and why they went the way they did.
A hallucinated name isn't a risky package — it's no package. slopgate gives
a registry 404 its own verdict (nonexistent) rather than folding it into
"block", and short-circuits there: nothing to be fresh about, nothing for
pkgxray to fetch. It always denies, under every policy. This is the single most
common thing an LLM gets wrong, and it's the cheapest check, so it runs first.
A brand-new package isn't suspicious (every good package was new once); a low-download package isn't either (plenty of legitimate niche tools). It's the conjunction — just published and almost nobody's using it — that matches a name squatted moments after an LLM invented it. Requiring both keeps an established package from ever being flagged this way. "Too new to have download stats yet" reads as low, because that's part of the just-squatted signal.
The obvious attack on a command-line gate is to not name the package on the
command line: write it into package.json, then run a bare npm install.
slopgate reads the manifest's direct dependencies and gates each by name.
It reads only direct deps — a hallucinated package is one the agent wrote, not
a transitive it doesn't control — and skips non-registry sources so a git: or
file: dependency is never false-denied.
OSV lookups, static heuristics, and prompt-injection detection live in pkgxray
and stay there. slopgate calls pkgxray guard <ref> --format json as a
subprocess and folds the verdict in. Duplicating that logic would mean two
things to keep correct and in sync; one source of truth is the whole point.
A missing pkgxray denies with install instructions (not a cryptic mid-install
error). A pkgxray that can't produce a verdict maps to review, not a false
allow. In skipPkgxray mode — where there's no pkgxray backstop — a registry
lookup error resolves to review, not allow. And an ask is enforced as a
block on agents that can't prompt. There is no path where uncertainty opens the
gate.
make build # build ./slopgate (needs the hookshot sibling repo)
make test # go test -race ./...
make vet # go vet
make dist # cross-compile release binaries for all platforms
make help # list targets
Tests are hermetic: the registry client is exercised against an httptest
server and the pkgxray subprocess against a pure-Go fake Runner, so the suite
needs neither the network nor pkgxray installed. Re-record the demo GIF with
vhs:
bash demo/record.sh
v1 is the hallucination gate for npm/npx only. Deliberately out of scope (clean extension seams left where natural): PyPI/pip, pnpm/yarn/bun clients, cross-registry confusion checks, fuzzy typosquat name-similarity, and any review of agent-written code.
MIT — see LICENSE. Built to guard the installs you didn't write.
FAQs
Install-gate hook that blocks slopsquatted / hallucinated npm packages before an AI coding agent installs them.
The npm package slopgate-cli receives a total of 3 weekly downloads. As such, slopgate-cli popularity was classified as not popular.
We found that slopgate-cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.