MCP server security auditor — deterministic engine + AI-native behavioral analysis
Project description
MCP server security auditor. Two modes of operation:
- Claude Code plugin — AI-native deep audit. Reads source code semantically, probes tools, detects behavioral mismatches, maps cross-server attack chains. Interactive HTML report.
- Standalone CLI — deterministic scan. 14 Semgrep rules, config health checks, SARIF output. Works in CI/CD without Claude.
What works today
| Feature | Status | How |
|---|---|---|
| Config health scanner | Working | Dead servers, scope conflicts, credential exposure, supply chain, CVE checks |
| Semgrep code analysis | Working | 14 rules (Python + JS/TS): injection, traversal, SSRF, eval, secrets, stdout |
| SARIF output | Working | GitHub Security tab integration |
| JSON output | Working | Machine-readable for CI/CD |
| Terminal output | Working | Rich colored tables with risk scores |
| CI exit codes | Working | --fail-on critical returns exit 1 |
| LLM behavioral analysis | Working | Anthropic SDK, behavioral mismatch detection (optional) |
| Audit history | Working | JSONL log, cross-run comparison (new/confirmed/fixed) |
| Self-security audit | Working | 10 vulnerabilities found and fixed in own code |
| Claude Code plugin | Working | AI-driven deep audit with HTML report |
| 75+ tests | Passing | Unit, security, stress, edge cases, Hypothesis fuzzing |
What doesn't work yet
- Cross-server chain detection in CLI (exists in Claude Code plugin only)
- Auto-fix in CLI (exists in Claude Code plugin only)
- HTML report generation in CLI
- MCPTox benchmark validation
- Community rule contributions
Install
Claude Code plugin (deep AI-native audit):
claude plugin marketplace add m0rvayne/mcp-redteam
claude plugin install mcp-redteam
/mcp-redteam
Standalone CLI (deterministic, CI/CD ready):
pip install mcp-redteam
mcp-redteam scan ./your-mcp-server --no-llm
Requires Python 3.10+. Semgrep installed separately for code analysis: pip install semgrep.
What it checks
Config Health (deterministic)
Dead/disconnected servers, scope conflicts (same server in multiple scopes), credentials in git-tracked config files (CVE-2025-59536), unpinned npx/uvx packages (supply chain), enableAllProjectMcpServers bypass (CVE-2026-21852), orphaned MCP processes.
Code Security (Semgrep, 14 rules)
| Rule | What it detects | Languages |
|---|---|---|
| Shell injection | subprocess + shell=True with user input | Python |
| Path traversal | open()/Path() without realpath check | Python, JS/TS |
| SSRF | HTTP requests with user-controlled URL | Python, JS/TS |
| Eval injection | eval()/exec()/new Function() with user input | Python, JS/TS |
| Hardcoded secrets | API keys, tokens, passwords in source | Python, JS/TS |
| Stdout pollution | print()/console.log() in MCP handlers | Python, JS/TS |
| Missing error handling | Tool functions without try/except | Python |
| Credential in response | API keys/tokens in tool return values | Python |
Based on 48+ CVEs, OWASP MCP Top 10, and research from Invariant Labs, Trail of Bits, Palo Alto Unit 42, OX Security, and Snyk.
LLM Behavioral Analysis (optional, requires API key)
- Behavioral mismatch: tool description claims X, code does Y
- Hidden operations: undeclared network requests, file writes, subprocess calls
- Credential mishandling: secrets logged, leaked in errors, stored insecurely
How it compares
| mcp-scan (Snyk) | Cisco MCP Scanner | mcp-redteam | |
|---|---|---|---|
| Approach | Static description scan | YARA + LLM-as-judge | Semgrep taint + LLM behavioral |
| Reads source code | No | Python only | Yes — Python + JS/TS |
| Config validation | No | Config discovery | Yes — 6 checks, CVE detection |
| Behavioral mismatch | No | No | Yes (LLM layer) |
| SARIF output | No | No | Yes |
| CI exit codes | Yes | No | Yes |
| Self-tested | Unknown | Unknown | 75+ tests, self-security audit |
| Cloud dependency | Snyk API required | Cisco API (optional) | No — fully local |
Why not just use mcp-scan?
mcp-scan reads what a server says about itself — tool descriptions. mcp-redteam checks what a server actually does — source code analysis + behavioral analysis.
A server with clean descriptions but leaky code: mcp-scan passes it. We catch it.
Real findings mcp-scan cannot detect (they live in code, not descriptions):
- Trello API keys in
.envcommitted to git - Instagram session cookies stored in plaintext
- AppleScript injection via unescaped clipboard input
- Google OAuth tokens with permissions
644
Audit History
Each audit saves a compact JSONL log to ~/Desktop/redteam-results/. On the next run, mcp-redteam reads previous results and compares:
- confirmed — found again, higher confidence
- new — first time seeing this
- fixed — was in previous audit, now gone
This turns LLM non-determinism into an advantage: each run is a new perspective, the intersection is ground truth.
Architecture
/mcp-redteam
|
+-----------------+
| Phase 0: Config |
+-----------------+
|
+-----------+
| Discovery |
+-----------+
|
| 1 server = 1 agent
|
+----------+ +----------+ +----------+ +----------+
| Agent-01 | | Agent-02 | | Agent-03 | | Agent-N |
| youtube | | trello | | instagram| | server-N |
| health | | health | | health | | health |
| arch | | arch | | arch | | arch |
| complete | | complete | | complete | | complete |
| security | | security | | security | | security |
+----+-----+ +----+-----+ +----+-----+ +----+-----+
| | | |
+------+-----+-----+------+
|
+-------------------------+
| Chain analysis + report |
+-------------------------+
|
+----------------+
| HTML + Fix |
+----------------+
Tests
75+ tests across 6 test files:
- test_semgrep.py — each vulnerable fixture detected, each benign fixture clean
- test_self_security.py — 21 tests: our own code audited for vulnerabilities
- test_stress.py — 1000/10000 findings, concurrent scans, unicode
- test_fuzzing.py — Hypothesis property-based: any input, no crash
- test_edge_cases.py — corrupt JSON, missing files, null bytes, timeouts
- test_models.py + test_formatters.py — unit tests for core logic
Current Limitations
- Plugin requires Claude Code with connected MCP servers
- CLI requires semgrep for code analysis (graceful skip if not installed)
- LLM analysis requires ANTHROPIC_API_KEY
- Destructive tests intentionally skipped — read-only probing only
- Source code analysis works for local servers; pip/npm packages may have limited access
- Plugin report quality scales with model capability (Opus > Sonnet > Haiku)
- False positive rate not yet measured on production MCP servers
Known False Positive Patterns
- SSRF rule triggers on
httpx.get()with URL built from config, not user input - Path traversal rule triggers on
open()where path is validated but validation isn't recognized as sanitizer - Stdout pollution flags
print()in__main__block (safe, not in MCP handler)
Docs
The docs/ folder is useful independently:
- attack-playbook.md — 18 attack categories, 48+ CVEs, payloads and detection methods
- best-practices.md — MCP server security checklist
- reference-server.md — secure server templates (Python + Node.js)
References
- OWASP MCP Top 10
- Invariant Labs — Tool Poisoning Attacks
- Trail of Bits — MCP Security Layer
- Palo Alto Unit 42 — MCP Attack Vectors
- OX Security — STDIO Design Flaw
- NSA — MCP Security Guidance
- Vulnerable MCP Project
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file redteam_mcp-0.2.0.tar.gz.
File metadata
- Download URL: redteam_mcp-0.2.0.tar.gz
- Upload date:
- Size: 25.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7ac5bdeb57960d2f8b4540608a5985f58755930abed92a569c558c4aa18ec67
|
|
| MD5 |
bf012d02720be8b1add1835c59c91d8b
|
|
| BLAKE2b-256 |
0ef8678aec57042832306dfcd9ec6ea270f32ddbfd16c1c43f8e3e60d4fca48a
|
Provenance
The following attestation bundles were made for redteam_mcp-0.2.0.tar.gz:
Publisher:
publish.yml on m0rvayne/mcp-redteam
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
redteam_mcp-0.2.0.tar.gz -
Subject digest:
b7ac5bdeb57960d2f8b4540608a5985f58755930abed92a569c558c4aa18ec67 - Sigstore transparency entry: 1789564544
- Sigstore integration time:
-
Permalink:
m0rvayne/mcp-redteam@8a28330f838014a09b0a4441efcc7aceae674b01 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/m0rvayne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a28330f838014a09b0a4441efcc7aceae674b01 -
Trigger Event:
push
-
Statement type:
File details
Details for the file redteam_mcp-0.2.0-py3-none-any.whl.
File metadata
- Download URL: redteam_mcp-0.2.0-py3-none-any.whl
- Upload date:
- Size: 37.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7e7adebc5f65e7016af163c46b854858036a65397df1df7d3140a7a66f9d3fa
|
|
| MD5 |
ddf400d64c5499018fa7024ee5b97b59
|
|
| BLAKE2b-256 |
9a6015fc84127dcde20ad67236b5b3825795aa273b16c31ac0e15be754af4458
|
Provenance
The following attestation bundles were made for redteam_mcp-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on m0rvayne/mcp-redteam
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
redteam_mcp-0.2.0-py3-none-any.whl -
Subject digest:
f7e7adebc5f65e7016af163c46b854858036a65397df1df7d3140a7a66f9d3fa - Sigstore transparency entry: 1789564661
- Sigstore integration time:
-
Permalink:
m0rvayne/mcp-redteam@8a28330f838014a09b0a4441efcc7aceae674b01 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/m0rvayne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a28330f838014a09b0a4441efcc7aceae674b01 -
Trigger Event:
push
-
Statement type: