{"_id":"@cruxet/mcp-audit","_rev":"2-60091af6761af5f6d328e6d2d3023163","name":"@cruxet/mcp-audit","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@cruxet/mcp-audit","version":"0.1.0","keywords":["mcp","security","audit","scanner","linter","cve","model-context-protocol","cursor","claude","windsurf","vscode","continue","codex","zed","ai-security","supply-chain","devsecops","ci"],"author":{"name":"Cruxet"},"license":"MIT","_id":"@cruxet/mcp-audit@0.1.0","maintainers":[{"name":"emrnel","email":"emreilhansenel@gmail.com"}],"homepage":"https://github.com/cruxet/mcp-audit","bugs":{"url":"https://github.com/cruxet/mcp-audit/issues"},"bin":{"mcp-audit":"bin/mcp-audit.js"},"dist":{"shasum":"f97db42b2fc9ee6c4273c9c003f2aa2c9ee34919","tarball":"https://registry.npmjs.org/@cruxet/mcp-audit/-/mcp-audit-0.1.0.tgz","fileCount":100,"integrity":"sha512-TWe8PlEq/2AuVaycpSjyOgD7SWKN3+kWTDpWcpnmCGZiiyYyUcOWGkOwpfpWiANpMNcGz26X0w1cpwzcr1FgtQ==","signatures":[{"sig":"MEUCIQDKfyWiWbW1Y8PWz+3GQ6n6VFZVXp7o3sAD8tVfKwcowwIgOwGTgloRHxFuYS+ORq5PUcqbH0UHqgSJEGolxYYTQDk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":175396},"main":"dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"5899a7cba71b9c1a0fda8b38285feda533ad7e11","scripts":{"dev":"tsx src/cli.ts","test":"vitest run","build":"tsc -p tsconfig.json","start":"node dist/cli.js","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"emrnel","email":"emreilhansenel@gmail.com"},"repository":{"url":"git+https://github.com/cruxet/mcp-audit.git","type":"git"},"_npmVersion":"10.5.0","description":"Local, zero-setup security linter for your MCP client configs. Catches command injection, hardcoded secrets, insecure transports, and known CVEs across Cursor, Claude, Windsurf, VSCode, Continue, Codex, and Zed. No account, no API calls, no data leaves yo","directories":{},"_nodeVersion":"20.12.2","dependencies":{"glob":"^10.3.10","chalk":"^5.3.0","json5":"^2.2.3","commander":"^12.0.0","smol-toml":"^1.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.7.0","vitest":"^1.6.0","typescript":"^5.4.0","@types/node":"^20.11.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-audit_0.1.0_1776997318231_0.34719281109565236","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cruxet/mcp-audit","version":"0.2.0","description":"Local, zero-setup security linter for your MCP client configs. Catches command injection, hardcoded secrets, insecure transports, and known CVEs across Cursor, Claude, Windsurf, VSCode, Continue, Codex, and Zed. No account, no API calls, no data leaves yo","homepage":"https://github.com/cruxet/mcp-audit","bugs":{"url":"https://github.com/cruxet/mcp-audit/issues"},"repository":{"type":"git","url":"git+https://github.com/cruxet/mcp-audit.git"},"author":{"name":"Cruxet"},"publishConfig":{"access":"public"},"keywords":["mcp","security","audit","scanner","linter","cve","model-context-protocol","cursor","claude","windsurf","vscode","continue","codex","zed","ai-security","supply-chain","devsecops","ci"],"license":"MIT","type":"module","bin":{"mcp-audit":"bin/mcp-audit.js"},"main":"dist/cli.js","scripts":{"build":"tsc -p tsconfig.json","dev":"tsx src/cli.ts","start":"node dist/cli.js","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"engines":{"node":">=18"},"dependencies":{"chalk":"^5.3.0","commander":"^12.0.0","glob":"^10.3.10","json5":"^2.2.3","smol-toml":"^1.3.0"},"devDependencies":{"@types/node":"^20.11.0","tsx":"^4.7.0","typescript":"^5.4.0","vitest":"^1.6.0"},"_id":"@cruxet/mcp-audit@0.2.0","gitHead":"a33752cb481788ee50d50b4ccbc458910e9fa000","types":"./dist/cli.d.ts","_nodeVersion":"20.12.2","_npmVersion":"10.5.0","dist":{"integrity":"sha512-kWX6jxxbquB+OLUqu7s5cl0dIU8VJcuPJWKc/M66SN5C/NsRpKkWQpCJbUgPw/ahxIQdfiyFV56BfFwje9LXEA==","shasum":"557580f8b6e482bbf3e5b4b0b3189e66b2e01cc3","tarball":"https://registry.npmjs.org/@cruxet/mcp-audit/-/mcp-audit-0.2.0.tgz","fileCount":108,"unpackedSize":221570,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCZ6nkOw2gO0Whl0x/XNBNj34eblp6ariQ343Ajtm25TQIgVL68a7WE+zpfQ9zd8Bb9h0MW590AQHERbIVXFPa+wvQ="}]},"_npmUser":{"name":"emrnel","email":"emreilhansenel@gmail.com"},"directories":{},"maintainers":[{"name":"emrnel","email":"emreilhansenel@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-audit_0.2.0_1777000724926_0.7219166661714729"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-24T02:21:58.061Z","modified":"2026-04-24T03:18:45.243Z","0.1.0":"2026-04-24T02:21:58.371Z","0.2.0":"2026-04-24T03:18:45.112Z"},"bugs":{"url":"https://github.com/cruxet/mcp-audit/issues"},"author":{"name":"Cruxet"},"license":"MIT","homepage":"https://github.com/cruxet/mcp-audit","keywords":["mcp","security","audit","scanner","linter","cve","model-context-protocol","cursor","claude","windsurf","vscode","continue","codex","zed","ai-security","supply-chain","devsecops","ci"],"repository":{"type":"git","url":"git+https://github.com/cruxet/mcp-audit.git"},"description":"Local, zero-setup security linter for your MCP client configs. Catches command injection, hardcoded secrets, insecure transports, and known CVEs across Cursor, Claude, Windsurf, VSCode, Continue, Codex, and Zed. No account, no API calls, no data leaves yo","maintainers":[{"name":"emrnel","email":"emreilhansenel@gmail.com"}],"readme":"# mcp-audit\n\n> Local, zero-setup security linter for your MCP client configs.\n\n[![npm version](https://img.shields.io/npm/v/@cruxet/mcp-audit.svg)](https://www.npmjs.com/package/@cruxet/mcp-audit)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![CI](https://github.com/cruxet/mcp-audit/actions/workflows/ci.yml/badge.svg)](https://github.com/cruxet/mcp-audit/actions/workflows/ci.yml)\n\n`mcp-audit` is a static analyzer for Model Context Protocol (MCP) configuration\nfiles. It catches command injection, hardcoded secrets, insecure transports,\ndangerous environment variables, and known vulnerable package references across\nevery major MCP client — **without an account, without a network call, and\nwithout sending anything to a third party.**\n\n```bash\nnpx @cruxet/mcp-audit\n```\n\nThat's the whole setup. It finds your configs, scans them with a deterministic\nrules engine, and prints actionable fixes. Works on Cursor, Claude Desktop,\nClaude Code, Windsurf, VSCode, Continue.dev, Codex, and Zed — on macOS, Linux,\nand Windows.\n\n## What this is — and what it isn't\n\n**This is:** a fast, offline linter for MCP *client* configuration files. Think\nof it as ESLint for your `~/.cursor/mcp.json` and friends. It looks at the\nconfig you've written and flags operational misconfigurations an attacker\ncould weaponize — wrong launcher, shell metacharacters in `args`, API keys\ncommitted to disk, `http://` where `https://` belongs, environment variables\nthat hijack dynamic linking, and packages with known CVEs.\n\n**This is not:** a runtime scanner. `mcp-audit` never starts your MCP servers,\nnever calls their `tools/list` endpoints, never sends tool descriptions to an\nLLM for analysis. If you want to audit what a third-party server *does* at\nruntime — prompt injection, tool poisoning, toxic flows — pair `mcp-audit`\nwith a runtime scanner like\n[Snyk Agent Scan](https://github.com/snyk/agent-scan) or\n[`@dj_abstract/mcp-audit`](https://www.npmjs.com/package/@dj_abstract/mcp-audit).\nThey answer \"is this server malicious?\"; this tool answers \"did I configure\nit safely?\"\n\n## What it checks\n\n| Rule | Checks for | Severity |\n| --- | --- | --- |\n| `MCP-AUDIT-001` Command Outside Allowlist | `bash`, `sh`, `cmd.exe`, absolute paths, non-standard launchers | critical / high / medium |\n| `MCP-AUDIT-002` Argument Injection | `-c` / `-e` / `--eval` flags, shell metacharacters, `curl … \\| sh`, command substitution | critical / high |\n| `MCP-AUDIT-003` Hardcoded Secret | OpenAI, Anthropic, GitHub, Slack, Google, AWS, JWT, PEM private keys, Bearer tokens | critical / high / medium |\n| `MCP-AUDIT-004` Insecure Transport | `http://` endpoints, exposed loopback, missing Authorization | high / medium / low / info |\n| `MCP-AUDIT-005` Environment Injection | `LD_PRELOAD`, `NODE_OPTIONS`, `DYLD_INSERT_LIBRARIES`, `PYTHONSTARTUP`, `BASH_ENV`, … | critical / high / medium |\n| `MCP-AUDIT-006` Suspicious Package | CVE-tagged packages, typosquats of well-known MCP servers | critical / high |\n| `MCP-AUDIT-007` Configuration Error | Missing `command`/`url`, conflicting transports, malformed blocks | medium |\n| `MCP-AUDIT-008` Unpinned Package Version | `npx foo` with no version, `@latest`/`@next`/`@beta` dist-tags, `github:` / URL / `file:` installs | high / medium |\n\nCVEs mapped include `CVE-2026-30623` (LiteLLM), `CVE-2026-30615`\n(Windsurf), `CVE-2026-34935` (PraisonAI), `CVE-2026-6130` (ChatboxAI),\n`CVE-2026-5023` (codebase-mcp), `CVE-2026-30625` (Upsonic),\n`CVE-2026-33224` (Bisheng), `CVE-2025-54994`\n(`@akoskm/create-mcp-server-stdio`), and others.\n\n## Supported clients\n\n| Client | Path |\n| --- | --- |\n| Cursor | `~/.cursor/mcp.json`, `%APPDATA%\\Cursor\\mcp.json` |\n| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json`, `%APPDATA%\\Claude\\claude_desktop_config.json`, `~/.config/Claude/claude_desktop_config.json`, `~/.claude/claude_desktop_config.json` |\n| Claude Code | `~/.claude.json`, `./.mcp.json` |\n| Windsurf | `~/.codeium/windsurf/mcp_config.json` |\n| VSCode | `~/Library/Application Support/Code/User/mcp.json`, `%APPDATA%\\Code\\User\\mcp.json`, `~/.config/Code/User/mcp.json`, `./.vscode/mcp.json` |\n| Continue.dev | `~/.continue/mcpServers/*.json`, `./.continue/mcpServers/*.json`, `~/.continue/config.json` |\n| Codex | `~/.codex/config.toml` |\n| Zed | `~/.config/zed/settings.json` |\n\nProject-level `.cursor/mcp.json`, `.vscode/mcp.json`, `.mcp.json`, and\n`.continue/mcpServers/` are scanned automatically from the current\nworking directory.\n\n## Usage\n\n```bash\n# Auto-discover and scan every supported config on this machine\nnpx @cruxet/mcp-audit\n\n# Scan a specific file (or many)\nnpx @cruxet/mcp-audit --config ~/.cursor/mcp.json\n\n# Scan specific project directories\nnpx @cruxet/mcp-audit --dir ./service-a --dir ./service-b\n\n# Skip global (home) or project scans\nnpx @cruxet/mcp-audit --skip-global\nnpx @cruxet/mcp-audit --skip-project\n\n# JSON output for CI/CD\nnpx @cruxet/mcp-audit --format json > audit-report.json\n\n# SARIF for GitHub Code Scanning\nnpx @cruxet/mcp-audit --format sarif --output mcp-audit.sarif\n\n# Markdown report\nnpx @cruxet/mcp-audit --format markdown --output mcp-audit.md\n\n# Hide findings below a threshold (useful for CI)\nnpx @cruxet/mcp-audit --min-severity high\n\n# Fail CI only on critical+\nnpx @cruxet/mcp-audit --fail-on critical\n\n# Quiet / verbose\nnpx @cruxet/mcp-audit --quiet\nnpx @cruxet/mcp-audit --verbose\n\n# No colors (pipes already auto-disable color)\nnpx @cruxet/mcp-audit --no-color\n```\n\n### Inventory\n\nSometimes you don't want a scan — you just want to know *what MCP servers you\nhave configured*. `inventory` lists every server across every discovered\nconfig, grouped by client and scope, with transport and package information.\nNo rules are evaluated, nothing is flagged.\n\n```bash\n# List every MCP server across all discovered configs\nnpx @cruxet/mcp-audit inventory\n\n# Inspect a single file\nnpx @cruxet/mcp-audit inventory --config ~/.cursor/mcp.json\n\n# Machine-readable output (for scripting / dashboards / baselines)\nnpx @cruxet/mcp-audit inventory --format json > mcp-inventory.json\n```\n\nUseful for:\n\n- Quick \"what's running on my machine?\" review before connecting a new server.\n- Security reviews and team audits — a single source of truth for MCP surface.\n- Capturing a baseline you can diff against later to catch silent additions.\n\n### Drift detection\n\nOnce you have a JSON scan report, you can diff it against a later run to\ncatch new or escalated findings without re-announcing noise that was already\nknown. Perfect for CI on pull requests.\n\n```bash\n# Capture a baseline today\nnpx @cruxet/mcp-audit --format json --output baseline.json\n\n# Later — in CI, on each PR, etc.\nnpx @cruxet/mcp-audit --format json --output current.json\nnpx @cruxet/mcp-audit diff baseline.json current.json --fail-on-new high\n```\n\n`diff` correlates findings by a stable fingerprint (rule + server + matched\nvalue) so it's resilient to line-number drift and re-formatting. It reports:\n\n- **New** — findings that didn't exist in the baseline.\n- **Resolved** — findings from the baseline that are now gone.\n- **Changed severity** — same issue, but severity escalated (e.g. after a CVE\n  publication) or de-escalated.\n- **Unchanged** — still present, still the same severity.\n\nWith `--fail-on-new <severity>`, the command exits non-zero only if a *new*\nor *escalated* finding meets or exceeds that severity — so an existing known\nissue won't keep tripping CI while you triage it.\n\nSupported output formats: `pretty` (default), `json`, `markdown`.\n\n### Exit codes\n\n| Code | Meaning |\n| --- | --- |\n| 0 | No issues (or only findings below `--fail-on`) |\n| 1 | Low-severity findings present |\n| 2 | Medium-severity findings present |\n| 3 | High-severity findings present |\n| 4 | Critical-severity findings present |\n| 10 | Scan error (invalid flag, unreadable file, …) |\n\n`inventory` always exits `0` on success.\n\n## CI/CD integration\n\n### GitHub Action (recommended)\n\nThe simplest way to wire this into CI is the official\n[`cruxet/mcp-audit-action`](https://github.com/cruxet/mcp-audit-action)\ncomposite action:\n\n```yaml\nname: MCP Audit\non: [push, pull_request]\n\njobs:\n  audit:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      security-events: write\n    steps:\n      - uses: actions/checkout@v4\n      - uses: cruxet/mcp-audit-action@v0\n        with:\n          fail-on: high\n          upload-sarif: true\n```\n\nIt handles Node setup, SARIF upload to GitHub Code Scanning, and artifact\nuploads for you.\n\n### Plain `npx` (any CI)\n\nIf you'd rather invoke the CLI directly:\n\n```yaml\nname: MCP Audit\non: [push, pull_request]\n\njobs:\n  audit:\n    runs-on: ubuntu-latest\n    permissions:\n      security-events: write\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with: { node-version: \"20\" }\n\n      - name: Audit MCP configs\n        run: npx @cruxet/mcp-audit --format sarif --output mcp-audit.sarif --skip-global\n\n      - name: Upload SARIF\n        if: always()\n        uses: github/codeql-action/upload-sarif@v3\n        with:\n          sarif_file: mcp-audit.sarif\n```\n\nPre-commit hook (`.git/hooks/pre-commit`):\n\n```bash\n#!/usr/bin/env bash\nnpx @cruxet/mcp-audit --skip-global --fail-on high --quiet || {\n  echo \"mcp-audit found high-severity MCP misconfigurations. Aborting commit.\" >&2\n  exit 1\n}\n```\n\n## Privacy\n\n`mcp-audit` runs entirely offline:\n\n- No network calls.\n- No telemetry.\n- No file writes (unless you pass `--output`).\n- No LLM calls — this is a deterministic rules engine.\n- No account, no API token.\n\nYour MCP configs, secrets, and findings stay on your machine. This makes the\ntool safe to run in regulated environments, air-gapped networks, and any\nworkflow where sending configuration data to a third party is off the table.\n\n## Development\n\n```bash\ngit clone https://github.com/cruxet/mcp-audit\ncd mcp-audit\nnpm install\nnpm run dev -- --config ./tests/fixtures/vulnerable-configs/vuln-bash-c.json\nnpm test\nnpm run build\n```\n\nProject layout:\n\n```\nsrc/\n  scanner/      # discovery + parser + orchestrator\n  rules/        # rule implementations (one file per rule)\n  reporters/    # pretty / json / sarif / markdown\n  inventory.ts  # inventory builder + pretty/json renderers\n  utils/        # platform, json-locator, logger\ntests/\n  fixtures/\n    safe-configs/\n    vulnerable-configs/\n```\n\nEach rule is self-contained in `src/rules/<rule>.ts` and exports a\n`Rule` object with `id`, `severity`, `category`, an optional `cve` array,\nand a `check` function returning `Finding` partials. Adding a new check\nis a matter of writing a new `Rule` and registering it in\n`src/rules/index.ts`.\n\n## About\n\n`mcp-audit` is built by the [Cruxet](https://github.com/cruxet) team —\nwe're building secure-by-default context orchestration for AI-native\ndevelopment teams.\n\n## Contributing\n\nIssues and PRs welcome. For new rules, include:\n\n1. A real-world CVE, advisory, or attack writeup as motivation.\n2. At least one fixture under `tests/fixtures/vulnerable-configs/`.\n3. At least one fixture under `tests/fixtures/safe-configs/` (to prevent\n   false-positive regressions).\n4. Three or more Vitest cases in `tests/rules.test.ts`.\n\n## License\n\nMIT © Cruxet\n","readmeFilename":"README.md"}