{
  "markdown": "<div align=\"center\">\n\n<img src=\"docs/banner.png\" alt=\"pkgxray — analyze packages before you install them\" width=\"820\">\n\n# pkgxray — pre-install security for npm packages, MCP servers, and AI agents\n\nInspect an npm package or MCP server **before** you install it or connect to it.\nYou get a `SAFE`, `REVIEW`, or `BLOCK` verdict, decided by fixed rules and backed\nby cited evidence. The analysis is static, runs on your machine, and has no\ndependencies. Normal scans never execute package code.\n\n[![npm version](https://img.shields.io/npm/v/pkgxray)](https://www.npmjs.com/package/pkgxray)\n[![npm downloads](https://img.shields.io/npm/dm/pkgxray)](https://www.npmjs.com/package/pkgxray)\n[![tests](https://github.com/adamsjack711-ux/pkgxray/actions/workflows/pkgxray-test.yml/badge.svg)](https://github.com/adamsjack711-ux/pkgxray/actions/workflows/pkgxray-test.yml)\n[![calibration benchmark](https://github.com/adamsjack711-ux/pkgxray/actions/workflows/pkgxray-benchmark.yml/badge.svg)](https://github.com/adamsjack711-ux/pkgxray/actions/workflows/pkgxray-benchmark.yml)\n[![license: MIT](https://img.shields.io/npm/l/pkgxray)](LICENSE)\n\n[**Website**](https://pkgxray.ca) · [**Documentation**](docs/README.md) · [**Calibration**](https://pkgxray.ca/stats) · [**Report a bug**](https://github.com/adamsjack711-ux/pkgxray/issues)\n\n<img src=\"docs/demo/hero.gif\" alt=\"pkgxray guard clearing express@4.21.0 with a SAFE A+ verdict, then blocking a trojaned sample with a BLOCK F verdict and a HIGH credential-access finding\" width=\"820\">\n\n<sub>Real runs: <code>guard</code> clears <code>express@4.21.0</code>, then blocks a sample modeled on the 2024 <code>@solana/web3.js</code> compromise.</sub>\n\n</div>\n\n## Highlights\n\n- **No runtime dependencies** — pure Node, and it all runs on your machine (~25 ms static pass).\n- **Normal scans never execute package code** — the tarball is read as bytes in quarantine.\n- **Cited verdicts from fixed rules** — every finding names the file and the evidence. No model decides the verdict, so text planted in a package cannot steer it.\n- **Built for the agent era** — check MCP servers before you connect, gate the installs an agent runs, and re-audit live MCP traffic.\n- **Calibrated, with a CI gate against regressions** — zero heuristic false blocks on the top-1000 most-downloaded packages.\n\n> **[1. Quick start](#quick-start)** · [2. What it scans & detects](#what-it-scans--detects) · [3. Verdicts](#verdicts) · [4. Usage](#usage) · [5. Integrations](#integrations) · [6. How it compares](#how-it-compares) · [7. Documentation](#documentation)\n\n## Why\n\nAI coding assistants install packages and connect to MCP servers quickly, and\noften no person reads the code first. Sonatype counted **more than 454,600 new\nmalicious open-source packages across monitored ecosystems in 2025**, over 99% of\nthem on npm\n([Sonatype](https://www.sonatype.com/state-of-the-software-supply-chain/2026/open-source-malware)).\n`npm audit` asks whether a package has a known CVE. pkgxray also asks what the\ncode does, before anything installs.\n\n## Quick start\n\n**1. Scan a known-benign package** (no install of pkgxray needed):\n\n```bash\nnpx --yes pkgxray@1.0.5 guard npm:express@4.21.0\n```\n\nIt stages the tarball in quarantine and runs the static and supply-chain checks.\nThere is no `npm install`, no lifecycle script, and no package code executed.\n\n<details>\n<summary>Sample output</summary>\n\n```text\nDecision: SAFE   Grade: A+ (99/100)\nNo high- or medium-risk indicators were found in the provided evidence.\n\nNotes:\n- INFO npm-vs-github-clean — npm tarball matches the linked GitHub repo at the\n  published version. (15/16 files match GitHub @4.21.0)\n```\n\n</details>\n\n**2. Read the verdict:**\n\n| Verdict | Exit | Meaning |\n|---|---:|---|\n| `SAFE` | `0` | No high- or medium-risk indicators; default policy permits promotion. |\n| `REVIEW` | `3` | Evidence is incomplete or a privileged capability needs human review. |\n| `BLOCK` | `2` | High-severity cited evidence — reject or investigate. |\n\n`SAFE` is not a proof that a package is harmless; static analysis cannot see a\npayload downloaded only at runtime. See the [threat model](docs/threat-model.md).\n\n**3. See a BLOCK on the supplied inert fixture:**\n\n```bash\nnpx --yes pkgxray@1.0.5 --file examples/onboarding-malicious.json --format markdown\n```\n\nThe fixture is inert source text that models a split-string SSH-key read and\nexfiltration. **It is never executed.** It returns `BLOCK` (exit `2`) with the\ncited file and evidence.\n\n**4. Add it to your workflow** — [rechecks & CI](docs/reference.md#monitoring-pkgxray-recheck),\n[MCP](docs/mcp.md#the-pkgxray-mcp-server), [Hookshot install gate](examples/hookshot/).\n\n> **Two execution models.** Default `guard` and `audit` scans are **static**, so\n> package code is never executed. Three surfaces are different: listing an MCP\n> server's tools may spawn it, `mcp-proxy` runs it behind a gate, and the opt-in\n> [`canary`](docs/canary-threat-model.md) *executes* the package in a sandbox to\n> confirm what it does. The canary can confirm that a package is malicious, but it\n> can never prove one is safe. Full boundary: [SECURITY.md](SECURITY.md#scope).\n\n## What it scans & detects\n\n**Scans** — `pkgxray guard npm:name@version` or `pypi:name@version`,\n`github:owner/repo`, a local directory, whole lockfiles across two ecosystems\n(npm: `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `package.json`; PyPI:\n`requirements.txt`, `poetry.lock`, `Pipfile.lock`, `pyproject.toml`), MCP\nservers, and AI-agent extensions.\n\n**Detects** — credential theft (incl. split-fragment paths), cloud\ninstance-metadata and secret-store harvesting, prompt injection, Unicode\nsmuggling, base64 payloads and stage-2 loaders, exfiltration, persistence\n(shell profile, OS scheduler, and injected CI/CD workflows), self-deleting\ndroppers, registry worm replication (install-time `npm publish`), npm\ninstall-hook and PyPI `setup.py` install-time execution, obfuscated computed-arg\nexecution, hallucinated / slopsquat names (a lockfile pin the registry never\npublished), known CVEs (via OSV, before download), npm↔GitHub artifact\ndivergence, trojaned updates (`recheck`), and MCP\ncapability-surface abuse.\n\nThe full coverage matrix is in the [threat model](docs/threat-model.md), along\nwith the known blind spot: a package that downloads its payload later. A\nside-by-side comparison table is on the [website](https://pkgxray.ca/#catches).\n\n## Verdicts\n\n| Verdict | You should |\n|---|---|\n| `SAFE` | Install. Only `safe` promotes out of quarantine by default. |\n| `REVIEW` | Inspect the quarantined copy before promoting. |\n| `BLOCK` | Do not install. Every finding names the file and evidence. |\n\nExit codes are stable and CI-friendly: **`0`** safe/allow · **`2`** block ·\n**`3`** review.\n\n## Usage\n\n```bash\npkgxray guard npm:some-package@1.2.3 [--format json]   # vet a package before install\npkgxray guard pypi:some-package@1.2.3                  # same, for a PyPI package (sdist staged + scanned)\npkgxray mcp --package npm:some-mcp-server@1.4.2 npx some-mcp-server   # vet an MCP server; --recheck catches the rug-pull\npkgxray audit package-lock.json [--deep]               # also: yarn.lock, pnpm-lock.yaml, package.json\npkgxray audit requirements.txt [--deep]                # PyPI: also poetry.lock, Pipfile.lock, pyproject.toml\npkgxray recheck package-lock.json                      # scheduled: non-zero only on a regression\n```\n\nOne optional `.pkgxray.json` tunes policy, and every surface reads it. No config\nmeans the strictest settings. Config can never allow a CVE away, every loosening\nis printed, and a scan that errors fails closed to `review`. Schema and rules:\n[configuration.md](docs/configuration.md) · [`.pkgxray.example.json`](.pkgxray.example.json).\n\n## Integrations\n\nOne engine behind every entry point. \"Works with\" means a documented setup\nguide, not a vendor-endorsed integration.\n\n| Where | What it does | Guide |\n|---|---|---|\n| Coding agents — Codex, Claude Code, Cursor, Windsurf | Gate installs and expose the audit tools to the agent | [coding-agents.md](docs/integrations/coding-agents.md) |\n| MCP clients | Vet a server before connect; run pkgxray itself as an MCP server | [mcp.md](docs/mcp.md) |\n| GitHub Actions / CI | Fail a build when a dependency crosses policy | [github-actions.md](docs/integrations/github-actions.md) |\n| Install gate — Hookshot | Run `guard` on every package an agent tries to install | [examples/hookshot/](examples/hookshot/) |\n| Runtime MCP gate | Proxy a live MCP server and gate every tool call | [`mcp-proxy`](docs/mcp.md#per-call-runtime-gate-pkgxray-mcp-proxy) |\n| Dependency monitoring | Re-vet installed deps and pre-vet upgrades on a schedule | [`recheck`](docs/reference.md#monitoring-pkgxray-recheck) |\n\n## How it compares\n\n`npm audit` and OSV-Scanner check for published CVEs, and pkgxray does not\nreplace them. Run it alongside them. The tools in the same lane are Socket.dev,\nOpenSSF Package Analysis, and Cisco MCP Scanner, which also analyze what package\ncode does. The full capability comparison is in\n[docs/comparison.md](docs/comparison.md) and on the\n[website](https://pkgxray.ca/#comparison).\n\n## Evidence\n\npkgxray records **zero heuristic false blocks on the top-1000 most-downloaded\npackages**, and CI gates against a regression ([scope and\nmethodology](docs/benchmark.md)). The published runs live at\n[pkgxray.ca/stats](https://pkgxray.ca/stats). The claim covers the most-installed\nset only. It is not a claim of zero false blocks on every package.\n\n## Documentation\n\n| Doc | What it covers |\n|---|---|\n| [architecture.md](docs/architecture.md) · [design.md](docs/design.md) | Pipeline, surfaces, principles |\n| [threat-model.md](docs/threat-model.md) | Scope, blind spots, prompt-injection stance |\n| [mcp.md](docs/mcp.md) · [mcp-registry.md](docs/mcp-registry.md) | MCP vetting, runtime proxy, registry entry |\n| [canary-threat-model.md](docs/canary-threat-model.md) | The opt-in behavioral canary |\n| [configuration.md](docs/configuration.md) · [reference.md](docs/reference.md) | `.pkgxray.json`, severity policy, `recheck`, cache server |\n| [benchmark.md](docs/benchmark.md) · [comparison.md](docs/comparison.md) | Calibration and how it compares |\n| [compatibility.md](docs/compatibility.md) · [json-schema.md](docs/json-schema.md) | 1.0 contract, `--format json` schema |\n\nStart at the [documentation index](docs/README.md).\n\n## Contributing\n\n```bash\nnpm test                 # zero-dep node --test suite\nnpm run benchmark        # calibration corpus: precision/recall + 0-false-block gate\nnpm run validate:website # regenerate + validate the calibration pages\n```\n\nPull requests are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) and the\n[Code of Conduct](CODE_OF_CONDUCT.md) first. Report vulnerabilities privately,\nas [SECURITY.md](SECURITY.md) describes. Releases publish to npm with provenance\n(SLSA attestation), and each one is gated on the tests, the calibration\nbenchmark, and pkgxray's own supply-chain guard.\n\n<div align=\"center\">\n<sub>Built by <a href=\"https://github.com/adamsjack711-ux\">Jack Adams-Lovell</a> · <a href=\"LICENSE\">MIT</a> · <a href=\"https://pkgxray.ca\">pkgxray.ca</a></sub>\n</div>\n",
  "bytes": 11201,
  "sha": "1721165d9bf651f99da49388bdb94b420910f86d9232c5ffdd63de7a6a3d490a",
  "repo_slug": "adamsjack711-ux/pkgxray",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_adamsjack711_ux_pkgxray_994b7a5b/readme"
}