@piiiico/mcpaudit
v1.0.0
Published
Static vulnerability scanner for MCP (Model Context Protocol) servers — detects shell injection, path traversal, SSRF, SQL injection, and more
Downloads
132
Maintainers
Readme
mcpaudit
Static vulnerability scanner for MCP (Model Context Protocol) servers.
Detects shell injection, path traversal, SSRF, SQL injection, hardcoded secrets, config theater, and missing authentication — in Node.js, Python, Rust, and Go MCP servers.
npx mcpaudit https://github.com/org/mcp-serverQuick Start
# Scan any public MCP server repo
npx mcpaudit https://github.com/executeautomation/mcp-database-server
# Short form also works
npx mcpaudit owner/repo
# JSON output (pipe to jq, CI, etc.)
npx mcpaudit owner/repo --json | jq '.findings[]'
# Verbose: show code snippets for each finding
npx mcpaudit owner/repo --verboseExample Output
🔍 mcpaudit — executeautomation/mcp-database-server
Type: node | Lines: 1247 | Score: 47/100
Summary: 1 CRITICAL, 2 HIGH, 1 MEDIUM
────────────────────────────────────────────────────────────
🔴 [CRITICAL] sql-injection
File: src/index.ts:89
multipleStatements:true allows stacked queries — amplifies SQL injection
🟠 [HIGH] sql-injection
File: src/index.ts:203
SQL query built with template literal — SQL injection risk
🟠 [HIGH] missing-auth
File: src/index.ts:45
MCP tool registration with no visible auth/token check nearby
🟡 [MEDIUM] config-theater
File: src/index.ts:12
Security config field defined but may not be enforced in validation logic
────────────────────────────────────────────────────────────Flags
| Flag | Description |
|------|-------------|
| --json | Compact JSON output (stdout stays clean) |
| --verbose | Show code snippets for each finding |
| --include-all | Scan all dirs including dist/build (default skips them) |
| --exclude-paths <frags> | Comma-separated path fragments to skip |
| --show-test-findings | Include findings in test/fixture files |
Pattern Catalog
14 vulnerability patterns across 4 languages (TypeScript/JS, Python, Rust, Go):
shell-injection
Detects user-controlled input flowing into shell execution APIs.
| ID | Severity | Languages | Description |
|----|----------|-----------|-------------|
| shell-injection-exec-template | CRITICAL | JS/TS | exec/execSync with template literal containing ${ |
| shell-injection-exec-concat | CRITICAL | JS/TS | String concatenation in exec/execSync |
| shell-injection-spawn-template | HIGH | JS/TS | Template literal in spawn() command argument |
| shell-injection-spawn-shell | HIGH | JS/TS | spawn() called with shell:true |
| shell-injection-os-system | CRITICAL | Python | os.system() with user-controlled arg |
| shell-injection-subprocess-shell | CRITICAL | Python | subprocess with shell=True |
| shell-injection-subprocess-fstring | HIGH | Python | f-string as first arg to subprocess |
| shell-injection-rust-shell | CRITICAL | Rust | Command::new("sh"/"bash") — launches interpreter |
| shell-injection-rust-format | HIGH | Rust | format!() in .arg() call |
| shell-injection-adb-py | CRITICAL | Python | ADB shell wrapper with non-literal arg |
| shell-injection-adb-js | CRITICAL | JS/TS | ADB shell call with template literal arg |
path-traversal
Detects unsanitized file paths from user input.
| ID | Severity | Languages | Description |
|----|----------|-----------|-------------|
| path-traversal-fs-var | HIGH | JS/TS | fs.* call with non-literal path |
| path-traversal-fs-template | HIGH | JS/TS | Template literal path in fs call |
| path-traversal-open-fstring | HIGH | Python | open() with f-string path |
| path-traversal-open-param | MEDIUM | Python | open() with apparent user-controlled arg |
| path-traversal-rust-fs | HIGH | Rust | std::fs::* with non-literal path |
| path-traversal-rust-path | HIGH | Rust | Path::new() with variable argument |
ssrf
Detects HTTP requests to attacker-controlled URLs.
| ID | Severity | Languages | Description |
|----|----------|-----------|-------------|
| ssrf-fetch | HIGH | JS/TS | fetch() with non-literal URL |
| ssrf-axios | HIGH | JS/TS | axios.* with non-literal URL |
| ssrf-http | HIGH | JS/TS | http/https.get with variable URL |
| ssrf-requests | HIGH | Python | requests.* with non-literal URL |
| ssrf-httpx | HIGH | Python | httpx.* with non-literal URL |
sql-injection
Detects unsafe SQL query construction.
| ID | Severity | Languages | Description |
|----|----------|-----------|-------------|
| sql-injection-multistatement | CRITICAL | JS/TS | multipleStatements:true in connection config |
| sql-injection-concat | HIGH | JS/TS | SQL built with string concatenation |
| sql-injection-template | HIGH | JS/TS | SQL built with template literals |
| sql-injection-fstring | HIGH | Python | execute() with f-string |
| sql-injection-percent | HIGH | Python | execute() with % formatting |
config-theater
Detects security-looking config keys that are defined but never enforced.
missing-auth
Detects MCP tool registrations with no visible auth check in the surrounding context.
hardcoded-secret
Detects credentials, tokens, and API keys assigned as string literals.
False Positive Reduction
mcpaudit uses several techniques to reduce noise:
- Context window: Primary patterns only promote to high severity when user-input identifiers (
args,params,request.*, etc.) appear within 10 lines. - Sanitizer detection: If a sanitizing call appears on the same line as the dangerous pattern, the finding is suppressed.
- Test file separation: Findings in
test/,__tests__/,spec/, fixtures, mocks — categorized astest, excluded from score by default. - Bundled file detection: Minified/bundled JS (long lines, multiple copyright blocks) excluded from production score.
- MCP SQL executor awareness: SQL injection in files that implement a
runQuery/executeSQLtool is downgraded (the pattern is expected).
Adding New Patterns
Fork the repo and add entries to src/patterns.ts:
{
class: "my-vulnerability",
severity: "HIGH",
languages: ["ts", "js"],
pattern: /dangerousFunction\s*\(\s*`[^`]*\$\{/,
contextPattern: /\b(args|params|input)\b/, // optional: context check
description: "Dangerous function called with user-controlled template literal",
sanitizerPattern: /sanitize\s*\(/, // optional: suppression on same line
}Then open a PR — all patterns are welcome.
Use as a Library
import { scanRepo } from "mcpaudit";
const result = await scanRepo("owner/repo", {
includeAll: false,
showTestFindings: false,
});
console.log(result.score); // 0-100 risk score
console.log(result.findings); // array of Finding objects
console.log(result.summary); // "2 CRITICAL, 1 HIGH"Validated Against Real CVEs
- executeautomation/mcp-database-server — SQL injection via
multipleStatements:true+ template literal queries. CVSS 8.8. - minhalvp/android-mcp-server — Shell injection via ADB wrapper receiving unvalidated tool arguments.
Trust Scoring at Scale
mcpaudit gives you the raw signal. getcommit.dev wraps it in a full trust score — provenance, maintainer history, dependency health, and more.
License
MIT
