@hailbytes/mcp-security-scanner

Scans Model Context Protocol (MCP) server configurations for common security issues: overprivileged tools, missing auth, prompt injection surface, and unsafe defaults.

npm version npm downloads License: MIT Bundle Size LinkedIn


What it does

Audit MCP server configurations and endpoints for the most common AI security mistakes — overprivileged tools, missing authentication, prompt injection attack surface, and insecure transport defaults. Integrates into CI/CD as a gate or run on-demand via CLI.


Install

npm install -g @hailbytes/mcp-security-scanner
# or use directly via npx
npx @hailbytes/mcp-security-scanner ./mcp-config.json

Quick Start

CLI

# Scan a local config file
npx @hailbytes/mcp-security-scanner ./mcp-config.json

# Scan a server endpoint URL (transport checks only — see note below)
npx @hailbytes/mcp-security-scanner https://my-mcp-server.example.com

# Output SARIF for GitHub Code Scanning + fail on findings
npx @hailbytes/mcp-security-scanner ./config.json --format=sarif --exit-code

URL mode vs. config-file mode. When the target is a URL, the scanner does not connect to or introspect the live server — it evaluates only the transport security derivable from the URL itself (MISSING_TLS for http://, INSECURE_TRANSPORT for ws://). It emits a URL_SCAN_LIMITED info note to make this explicit. Authentication, rate limiting, CORS, tool, and secret rules require a config file (.json/.yaml) to evaluate. Point the scanner at your MCP server configuration to run the full rule set.

Loopback carve-out. Cleartext transport to a loopback host — localhost (and any *.localhost name), 127.0.0.0/8, or ::1 — never leaves the machine, so MISSING_TLS and INSECURE_TRANSPORT do not fire on it (e.g. http://localhost:3000 and ws://127.0.0.1:9000 pass). Only non-loopback cleartext endpoints are flagged.

Programmatic

import { scan } from "@hailbytes/mcp-security-scanner";

const report = await scan({ configPath: "./mcp-config.json" });

console.log(report.findings);  // Finding[] — individual security issues
console.log(report.score);     // 0–100 risk score (higher = riskier)
console.log(report.passed);    // boolean — use as CI gate

Default gate semantics. report.passed (and the CLI exit code with no flags) is true only when the config has no CRITICAL and no HIGH findings and its risk score is under 50. Any single CRITICAL or HIGH finding fails the gate. Use --fail-on=<severity> to lower the threshold (e.g. --fail-on=medium) or --exit-code to fail on any finding at all.


What It Checks

  • Overprivileged tools — tools granted broader permissions than their declared function requires
  • Missing or weak authentication — unauthenticated transports, missing token validation
  • Prompt injection / tool poisoning — tool names and descriptions carrying instruction-like text (<IMPORTANT> blocks, "ignore previous instructions", "do not tell the user"), or output paths susceptible to injection
  • Missing or weak authentication — unauthenticated transports, missing token validation, and placeholder/default credentials (e.g. your-api-key-here, changeme) that pass length checks but aren't real secrets
  • Prompt injection surface — tool descriptions or output paths susceptible to injection
  • Tool poisoning — hidden/invisible Unicode characters in tool names and descriptions (ASCII smuggling via Unicode Tags, bidirectional overrides, zero-width characters) that a human reviewer can't see but the model reads in full
  • Unsafe defaults — insecure transport defaults, verbose error exposure, CORS wildcards

See Also


Part of the HailBytes open-source security toolkit.