mcpwatch-scanner
v0.2.0
Published
MCP server security scanner — 10 OWASP-aligned checks with A-F letter grade. Part of MCPWatch.
Maintainers
Readme
@mcpwatch/scanner
MCP server security scanner. 10 OWASP-aligned checks. A–F letter grade.
Part of MCPWatch — the public security leaderboard for MCP servers.
Install
npx @mcpwatch/scanner /path/to/mcp/repo
# or
npm i -g @mcpwatch/scanner
mcpwatch-scan /path/to/mcp/repoWhat it checks
| # | Check | Severity | |---|-------|---------| | MCP-01 | Command injection in tool handlers | Critical | | MCP-02 | Path traversal in file tools | Critical | | MCP-03 | Unauthenticated mutating tools | Critical | | MCP-04 | Prompt injection via tool descriptions | High | | MCP-05 | SSRF in URL-fetching tools | High | | MCP-06 | Hardcoded secret leakage | High | | MCP-07 | Over-permissive filesystem scopes | Medium | | MCP-08 | Missing rate limits | Medium | | MCP-09 | Outdated dependencies (known CVEs) | Medium | | MCP-10 | Missing input schema validation | Low |
Example output
MCPWatch audit — my-mcp-server
Scanned 14 files · 10 checks · 4 passed
CRIT [MCP-01] Template literal passed directly into execSync()
src/tools/shell.ts: execSync(`bash -lc ${cmd}...
→ Use parameterized execFile() / spawn(cmd, [args]) without shell:true.
HIGH [MCP-05] URL fetched from user input with no SSRF guard
src/tools/fetch.ts
→ Reject RFC1918 + link-local + cloud metadata IPs before fetching.
Score: 47/100 Grade: DProgrammatic API
import { scan } from "@mcpwatch/scanner";
const result = await scan({
name: "my-mcp",
source: "github",
sourceRef: "owner/repo",
sourceFiles: [...],
packageJson: {...},
toolDescriptions: [...],
});
console.log(result.score, result.grade, result.findings);License
MIT
