pkgbouncer
Checks npm package names and versions against OSV malware/advisory data and registry metadata, blocking known-malicious, nonexistent, typosquatted, too-new, or risky install-script packages. Also scans npm lockfiles and suggests safe versions.
Checks PyPI package names and versions against OSV malware/advisory data and registry metadata, blocking known-malicious, nonexistent, typosquatted, too-new, or risky packages. Also scans Python lockfiles and suggests safe versions.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@pkgbounceris axios@1.6.0 safe to add to my npm project?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
pkgbouncer
An install gate for AI coding agents. pkgbouncer sits between Claude Code (or any MCP-capable agent) and the package registries. Before a package is installed it checks the name and version against public malware and advisory feeds and blocks the install if the package is known-malicious, does not exist (hallucinated or slopsquatted), or looks like a typo of a popular package. It warns on releases younger than a few days, high-severity advisories, and install scripts. After an install it diffs the lockfile and flags anything risky that came in transitively. When it blocks, it tells the agent which version is safe so the agent can self-correct.
Covers npm, PyPI, crates.io, and Go.
pkgbouncer needs no account and no API key. It uses the free public OSV.dev database and the package registries, and nothing leaves your machine except package names.
Is it a tool, a hook, or an MCP server?
All three, over one rule engine. They differ in how much they can enforce:
Form | How it runs | Enforcement |
Hook | Claude Code calls it automatically before and after every shell command | Enforced. The agent cannot skip it. This is the install gate. |
MCP server | The agent can call it to check a package before editing a manifest | Advisory. The agent decides whether to ask. |
CLI | You or CI run | Exit code 1 on a blocked package |
Use the hook for protection and add the MCP server if you want the agent to check proactively.
Related MCP server: depscope-mcp
How it compares
Several tools guard installs. They differ in where they sit:
Socket Firewall, Aikido Safe Chain, and similar wrappers sit in front of the package manager. They protect a person typing the command, and can cover an agent only if its shell uses the wrapper.
Dependabot, Snyk, and similar scanners run on a schedule or in CI, after a package is already in your repository.
attach-guard is a Claude Code plugin that also uses a pre-install hook. It scores packages through Socket.dev and needs a Socket API token.
pkgbouncer is a Claude Code hook plus an MCP server and CLI that decides locally from public feeds. It covers bare installs and the post-install lockfile diff, and it requires no account.
If you already run one of these, pkgbouncer adds the agent-side gate. They do not conflict.
30-second install
npm install -g pkgbouncer
# Claude Code: adds PreToolUse + PostToolUse hooks on Bash and PowerShell to ~/.claude/settings.json
pkgbouncer install claude-codeFrom then on, in every new Claude Code session:
Named installs are gated.
npm i,pnpm add,yarn add,bun add,npx,pip install,uv add,poetry add,pipx install,cargo add,cargo install,go get,go install. A blocked install returns the reason and a suggested safe version to the model.Bare installs are gated. On
npm install,npm ci,pnpm install,yarn, orbun install, every package.json dependency the lockfile does not yet satisfy is checked first. This is the "agent edited package.json, then ran npm install" path.Transitive hits are caught. Before any install the lockfile is snapshotted. After it, only the newly added packages are scanned against OSV, and malware or critical advisories are reported back to the model with removal instructions. Works for all four ecosystems.
Example of what the agent sees:
[pkgbouncer] BLOCKED lodahs@0.0.1-security
- (known-malicious) lodahs@0.0.1-security is a known malicious package (MAL-2025-25502: Malicious code in lodahs (npm)).
- (typosquat) lodahs looks like a typo of the popular package "lodash". Confirm you meant lodahs.
-> No safe version found; pick a different package.
Install blocked by pkgbouncer. Use the suggested safe version or a different package, then retry.Cursor: pkgbouncer install cursor writes a beforeShellExecution hook following Cursor's documented format. It has not been verified against a live Cursor install yet.
MCP server
The same checks are exposed as MCP tools so an agent can ask before it edits a manifest directly.
Claude Code:
claude mcp add pkgbouncer -- pkgbouncer mcpCursor (~/.cursor/mcp.json or .cursor/mcp.json):
{ "mcpServers": { "pkgbouncer": { "command": "pkgbouncer", "args": ["mcp"] } } }Tool | Purpose |
| Allow / warn / deny for |
| Scan every lockfile in a directory for known-malicious packages and critical advisories. |
| Newest version with no malware, no critical advisory, and older than the policy minimum age. |
CLI
pkgbouncer check lodash react@18 @types/node # npm by default; exit 1 if any is blocked
pkgbouncer check pypi:requests==2.31.0 crates:serde@1 go:github.com/gin-gonic/gin@v1.9.1
pkgbouncer check --ecosystem PyPI requests numpy
pkgbouncer check --json axios # machine-readable verdicts
pkgbouncer scan ./my-project # all lockfiles in the dir, exit 1 on hitsLockfiles understood: package-lock.json, npm-shrinkwrap.json, pnpm-lock.yaml, yarn.lock, bun.lock, uv.lock, poetry.lock, requirements.txt (pinned lines only), Cargo.lock, go.sum.
Rules
Rule | Signal | Default |
| OSV record with a | deny |
| OSV / GitHub / PyPA / Go advisory for this version | CRITICAL deny, HIGH warn |
| Package or version not on the registry (hint if it resembles a popular name) | deny |
| Published less than | warn (deny with |
| Edit distance 1 or 2 from a bundled popular name (npm, PyPI, crates) | warn |
| npm version declares preinstall / install / postinstall | warn |
| OSV or registry unreachable | warn (deny with |
Policy
Put pkgbouncer.json in the project root, or ~/.pkgbouncer/policy.json for a user-wide default. All fields are optional.
{
"minAgeDays": 3,
"strict": false,
"failClosed": false,
"allow": ["@mycompany/*", "internal-tool"],
"deny": ["event-stream@<4", "colors@>1.4.0"]
}allowentries short-circuit every rule.denyentries always block.Entries are
name,name@semver-range, or@scope/*.
Environment variables: PKGBOUNCER_HOME (default ~/.pkgbouncer), PKGBOUNCER_CACHE_DIR, PKGBOUNCER_OSV_URL, PKGBOUNCER_NPM_REGISTRY, PKGBOUNCER_PYPI_URL, PKGBOUNCER_CRATES_URL, PKGBOUNCER_GOPROXY_URL.
What it does and does not catch
pkgbouncer is feed-based. It catches what has been reported to OSV.dev (which ingests the OpenSSF malicious-packages list, the GitHub Advisory Database, PyPA advisories, RustSec, and the Go vulnerability database) and what registry metadata reveals. Most malicious packages are classified within three days of publication, and the too-new rule buys you that window. It does not analyze package code and will not catch a brand-new compromise before anyone reports it.
Transitive dependencies are judged after the install, from the lockfile diff, not before. A malicious transitive package will land on disk once and be reported immediately; the agent is told to remove it. Pair pkgbouncer with --ignore-scripts (npm 12 does this by default) for defense in depth.
Results are cached under ~/.pkgbouncer/cache (advisories 1 hour, registry metadata 6 hours, misses 10 minutes). Lookups go to OSV and the registries only; nothing about your project leaves your machine except package names.
Exit codes
Command | 0 | 1 | 2 |
| allow or warn | at least one deny | usage or no lockfile |
| allow or warn | deny (blocks in PreToolUse; reports to the model in PostToolUse) | |
| always; verdict is in stdout JSON |
If pkgbouncer itself crashes inside a hook it exits 0 so the agent is never wedged by the gate.
Status
Version 0.1.0, early release. The Claude Code hook has been verified in live Claude Code sessions on Windows. The Cursor hook is written to Cursor's documented format but has not been tested in a live Cursor install. Bug reports and false positives are very welcome.
Contributing
Contributions are welcome. Read CONTRIBUTING.md for setup, the code map, and the ground rules. Please report vulnerabilities privately as described in SECURITY.md, and follow the Code of Conduct.
git clone https://github.com/rayan1810/pkgbouncer.git
cd pkgbouncer
npm install
npm run build
npm test # vitest, no network needed
node dist/cli.js check lodashDesign and plans: docs/superpowers/specs/ and docs/superpowers/plans/. Release history is in CHANGELOG.md.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
Protects AI coding agents from installing malicious open source packages. Every npm and PyPI package is checked against SafeDep’s real-time threat intelligence before installation.
Check packages for CVEs, slopsquatting, and CISA KEV before your AI agent installs them.
Package intelligence for AI agents across npm, PyPI, crates.io and deps.dev. No API keys.
Package intelligence for AI agents across npm, PyPI, crates.io and deps.dev. No API keys.
Related MCP Servers
- AlicenseAqualityFmaintenanceDependency security & health auditing for AI agents with no account or API key required.22MIT
- AlicenseNot gradedqualityCmaintenanceValidates and checks packages across 19 ecosystems to prevent AI agents from installing hallucinated, deprecated, or malicious packages.14 npmAGPL 3.0
- AlicenseAqualityAmaintenanceEnables AI coding agents and CI to vet npm dependencies before they reach the lockfile, flagging hallucinated, slopsquatted, or otherwise risky packages with evidence-backed verdicts.327 npm4MIT
- AlicenseAqualityBmaintenanceEnables checking packages across npm, PyPI, Go, Maven, Cargo, NuGet, and RubyGems for existence, deprecation, known vulnerabilities, and license issues before installation, providing verdicts like does_not_exist, risky, verify, or ok.31MIT