Skip to main content
Glama

npmguard

A native pre-install risk gate for npm packages, with an MCP tool for AI coding agents. Pre-install risk scoring + MCP server, distributed outside the npm ecosystem so it can't be compromised by the thing it's protecting you from.

NOTE

v0.1 is a risk checker + MCP verdict gate. It is not yet a real npm wrapper, installer, or sandbox. npmguard check and npmguard install both produce a verdict; the actual npm install subprocess execution and cross-platform sandbox land in v0.2. See the roadmap below.

CI Release Latest release License: MIT

npmguard block verdict — atlas-ragnarok theme

npmguard install lodahs — a real typosquat of lodash, refused before lifecycle scripts can run:

npmguard refusing to install a typosquat — atlas-ragnarok theme

Also available as GIF or MP4. Live verdict against the npm registry — lodahs is in OSV's malware namespace (MAL-2025-25502). Theme: atlas-ragnarok. Regenerate with sh docs/_theme/gen.sh (needs vhs, ffmpeg, webp, pillow, numpy).


Why

Across 2025–2026 the npm ecosystem absorbed a series of worm-style supply chain attacks that ran inside preinstall / install / postinstall scripts the moment a downstream user ran npm install — Shai-Hulud (Sep 2025), SHA1-Hulud (Nov 2025), the Axios compromise (Mar 2026), Mini Shai-Hulud (May 2026). Defender wins or loses before the install completes, not after.

Existing defenses leave a specific gap:

  • npq, safe-npm / socket npm, npm-risk ship as npm packages. They run on the thing they're protecting you from. If the wrapper is ever compromised, you've made the problem worse.

  • pnpm v10+, Bun disable lifecycle scripts by default — but only for users who've moved off npm. The npm majority is unprotected.

  • npm audit, Snyk, Dependabot, lavamoat/allow-scripts are excellent at CVE scanning and allow-list management, but they're not a pre-install heuristic gate, and none of them gate AI coding assistants like Claude Code, Cursor, or Windsurf when they run npm install on your behalf.

npmguard fills the specific gap of pre-install risk scoring + AI-agent gate via MCP, shipped as a single binary outside npm. Zero external dependencies at runtime beyond the registries it queries.


Install

Pick whichever fits your machine:

# macOS (Apple Silicon)
curl -L -o npmguard.tar.gz \
  https://github.com/AyoubTadlaoui/npmguard/releases/latest/download/npmguard-v0.1.2-aarch64-apple-darwin.tar.gz
tar -xzf npmguard.tar.gz
sudo mv npmguard-v0.1.2-aarch64-apple-darwin/npmguard*  /usr/local/bin/

# macOS (Intel)
#   https://github.com/AyoubTadlaoui/npmguard/releases/latest/download/npmguard-v0.1.2-x86_64-apple-darwin.tar.gz

# Linux (x86_64)
#   https://github.com/AyoubTadlaoui/npmguard/releases/latest/download/npmguard-v0.1.2-x86_64-unknown-linux-gnu.tar.gz

# Linux (aarch64)
#   https://github.com/AyoubTadlaoui/npmguard/releases/latest/download/npmguard-v0.1.2-aarch64-unknown-linux-gnu.tar.gz

# Windows (x86_64)
#   https://github.com/AyoubTadlaoui/npmguard/releases/latest/download/npmguard-v0.1.2-x86_64-pc-windows-msvc.zip

# Build from source (any OS with Rust ≥ 1.75)
cargo install --git https://github.com/AyoubTadlaoui/npmguard --bin npmguard
cargo install --git https://github.com/AyoubTadlaoui/npmguard --bin npmguard-mcp

# Prebuilt binaries
#   https://github.com/AyoubTadlaoui/npmguard/releases

Every release ships a SHA256SUMS.txt — verify before extracting:

shasum -a 256 -c <(grep npmguard-v0.1.2-aarch64-apple-darwin.tar.gz SHA256SUMS.txt)

Docker (npmguard-mcp only)

docker pull ghcr.io/ayoubtadlaoui/npmguard-mcp:latest
docker run --rm -i ghcr.io/ayoubtadlaoui/npmguard-mcp:latest

The Docker image is provided for MCP catalogs and CI; native binaries remain the recommended local install path. The image ships only the npmguard-mcp server (not the CLI), runs as a non-root user, and has no exposed ports — MCP hosts communicate over stdio.

Homebrew tap, Scoop bucket, curl ... | sh installer, and AUR land with v0.2 alongside the sandbox layer. See DISTRIBUTION.md (planned) for the full channel matrix.


Quickstart — CLI

# Evaluate the latest version, no install.
npmguard check axios

# Pinned version, JSON output (machine-readable for CI).
npmguard check --json @ctrl/tinycolor@4.1.1

# Install path: v0.1 prints the verdict and stops; v0.2 will run `npm install`
# inside the sandbox layer if the verdict allows it.
npmguard install lodash@4.17.21

# Auto-accept warn-level (still refuses block-level).
npmguard install --yes some-fresh-package

Sample output, real live verdict against the registry:

npmguard  lodahs@0.0.1-security  →  score 115 / 200  (block, thresholds warn=30 block=70)
   10 pts  SoleMaintainer       single maintainer: adam_baldwin
   25 pts  Typosquat            name 'lodahs' is 1 edit away from popular package 'lodash'
   80 pts  KnownCve             1 CONFIRMED MALICIOUS by OSV for this version: MAL-2025-25502
blocked: refusing to install lodahs (score 115 ≥ block threshold 70)

All flags:

Flag

Default

Meaning

--json

false

Emit verdict as JSON instead of colored text

--no-color

false

Disable ANSI color escapes

--no-cache

false

Skip the local SQLite verdict cache

-v / -vv

warn

Increase log verbosity

--yes (install only)

false

Auto-accept warn-level verdicts; block-level still refuses


Quickstart — MCP

The npmguard-mcp binary speaks the Model Context Protocol over stdio. Add it to your MCP host's config (for Claude Code, that's ~/.claude.json):

{
  "mcpServers": {
    "npmguard": {
      "command": "/usr/local/bin/npmguard-mcp"
    }
  }
}

It exposes one tool, install_package(name, version?), returning a structured verdict the model can act on:

{
  "package": "lodahs",
  "resolved_version": "0.0.1-security",
  "level": "block",
  "score": 115,
  "signals": [
    { "kind": "SoleMaintainer", "points": 10, "detail": "single maintainer: adam_baldwin" },
    { "kind": "Typosquat", "points": 25, "detail": "name 'lodahs' is 1 edit away from popular package 'lodash'" },
    { "kind": "KnownCve", "points": 80, "detail": "1 CONFIRMED MALICIOUS by OSV for this version: MAL-2025-25502" }
  ],
  "recommendation": "Block — do NOT install this package without explicit user override. Present the signals and ask the user to confirm."
}

The model gets the recommendation in its own message, so even if the user said "just install whatever you need", the assistant has the structured signal to stop and ask.


Risk signals

Signal

Points

Triggered when

LifecycleScripts

30

Package defines preinstall, install, or postinstall

PackageAge

25 / 10

Version published < 7 / 30 days ago

MaintainerChurn

20

Version published after a > 180-day publish gap (dormant package resurrection)

SoleMaintainer

10

Package has exactly one maintainer

RepoHealth

15 / 10

Linked GitHub repo is archived / has zero stars and no commits in 6 months

Typosquat

25

Name is one Damerau-Levenshtein edit from a popular package (catches char swaps like lodahslodash)

KnownCve

80 / 50 / 20 / 10 / 5

OSV.dev advisory present. 80 if it's a MAL-* (OSV's confirmed-malicious-package namespace). Otherwise CVSS critical / high / medium / low.

Deprecated

10

npm registry marks this version deprecated

Composite score is the sum (capped at 200). Default thresholds: warn ≥ 30, block ≥ 70. Tunable per project via config (planned for v0.2).

Weights are starting values, not science. They will be tuned against corpus/ and the values published as part of each release. PRs welcome.


What npmguard does NOT do

Honesty is the contract.

npmguard cannot prove packages are safe. It can stop known-malicious packages (OSV MAL-*), flag typosquats, surface lifecycle scripts / package age / maintainer churn, and route AI coding agents through the same verdict. That's it. Everything below is what the v1.0 sentence will eventually add — see ROADMAP.md.

What's still missing in v0.1:

  • Doesn't catch attacks that pass all heuristic checks. A clean-history maintainer-account-takeover that ships a release matching every "looks normal" signal will still install. The v0.2 release-anomaly engine (per-version package.json diff) is the planned answer.

  • Doesn't yet verify npm provenance / package signatures. A historical provenance attestation suddenly missing is a strong takeover signal — that lands in v0.3.

  • Doesn't yet sandbox lifecycle scripts or wrap the real npm install subprocess. v0.1 surfaces the verdict and stops; v0.2 ships the sandbox (landlock / sandbox-exec / Job Object) + --ignore-scripts enforcement + per-script allow-list.

  • Doesn't protect against malicious code that runs at import time, not install time. If a package is benign at install but evil when imported, this tool isn't in the path. That's a runtime-sandbox problem and is deliberately out of scope — see ROADMAP.md.

  • Doesn't replace npm audit, Snyk, Socket, Dependabot, or code review. It's an additional layer. v0.3 adds --with npm-audit / --with osv-lockfile / --with socket adapters so npmguard becomes the policy gate on top of them rather than a redundant scanner.

  • Is not a guarantee. Any tool claiming "secure" is lying. This one says "reduces blast radius" and stops there.


Versioning & releases

npmguard follows Semantic Versioning. While the project is 0.x:

  • The CLI is treated as stable for end users — flag names and exit codes won't change without a major bump.

  • The MCP tool surface (install_package input/output schema) may make minor additive changes between 0.x releases. Anything breaking is called out in CHANGELOG.md.

Tagged releases publish prebuilt binaries to the Releases page (macOS x86_64 + arm64, Linux x86_64 + arm64, Windows x86_64) via a cross-platform GitHub Actions matrix.

Roadmap (full reasoning + considered-and-rejected scope in ROADMAP.md):

Phase

Headline

v0.1 (shipped)

Risk engine + CLI + MCP server + SQLite cache + GitHub Releases

v0.2

Real npm install execution + per-OS sandbox + release-anomaly engine (per-version package.json diff) + Homebrew/Scoop/AUR/install.sh distribution

v0.3

Provenance / signature verification + scanner adapters (--with npm-audit, --with osv-lockfile, --with socket) + SBOM generation

v0.4

npmguard.toml policy file + CI mode + waivers

v0.5

Organization presets + MCP marketplace placement (Claude Code, Cursor, Smithery)

v1.0

Frozen Rust API, frozen MCP tool schema, frozen JSON output, integration into AI-assistant default docs

Runtime sandboxing (npmguard run npm test) is deliberately out of scope — see ROADMAP.md § Considered and kept out of scope for the reasoning.


Contributing

PRs and issues welcome. The short version:

cargo fmt --all
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
NPMGUARD_CORPUS=1 cargo test --test corpus -- --nocapture   # live network test

Open the PR once that's clean.


License

MIT — see LICENSE.


About the author

Ayoub TadlaouiAtlas Kaisar — a problem-solver from Morocco, building software since 2016.

"High performance knows no part-time commitment."

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
3Releases (12mo)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AyoubTadlaoui/npmguard'

If you have feedback or need assistance with the MCP directory API, please join our Discord server