mcp-patch
Static security scanner for Python MCP server code.
43% of popular MCP servers have shell injection vulnerabilities. No existing tool does AST-level scanning with MCP context awareness. This one does.
Real CVEs this would have caught
- CVE-2025-53967 (Framelink Figma MCP) — shell injection via unsanitized tool parameters
- CVE-2025-6514 (mcp-remote, 437K downloads) — arbitrary command execution via unsanitized tool params
Install
pip install mcp-patch
mcp-patch scan my_server.py
Usage
# Scan a single file
mcp-patch scan server.py
# Scan a directory
mcp-patch scan ./servers/
Example output
Scanning server.py...
CRITICAL shell_injection line 14
subprocess.run(f"ls {path}", shell=True)
subprocess.run(shell=True) — tool param 'path' flows to shell
Fix: Use subprocess.run([cmd, shlex.quote(arg)]) without shell=True
HIGH path_traversal line 28
open(filename)
open(filename) — tool param 'filename' used as file path without validation
Fix: Use (base_dir / Path(filename).name).resolve() and verify result starts with base_dir
Found 2 issues (1 CRITICAL, 1 HIGH) in 1 file.
Checks
| Check | Severity | What it detects |
|---|---|---|
shell_injection |
CRITICAL | subprocess.run/Popen/call(f"...{param}", shell=True), os.system(), os.popen() with tool params |
path_traversal |
HIGH | open(param), Path(param) with a tool param passed directly as a path |
ssrf |
HIGH | requests.get/post(url), httpx.get(url), urllib.request.urlopen(url) where url is a tool param |
Only functions decorated with @tool or @mcp.tool() are scanned. Plain helper functions are ignored.
How it works
Pure stdlib. No network calls. No LLM. Parses your Python source with the ast module, finds @tool decorated functions, collects their parameter names, then walks each function body looking for dangerous call patterns where user-controlled params flow into dangerous sinks.
False positives
This is an MVP scanner — it prefers to over-report rather than miss real vulnerabilities. A path_traversal finding on open(filename) is real even if you have runtime validation elsewhere; the fix is to move validation into the same function so the scanner (and reviewers) can see it.
Development
python -m pytest tests/
No external dependencies. Python 3.9+.
Metadata
Release files for mcp-patch 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mcp_patch-0.1.0.tar.gz | 10.0 kB | Without provenance | Details for mcp_patch-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mcp_patch-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for mcp_patch-0.1.0-py3-none-any.whl |
Total release size: 18.4 kB
Release files / mcp_patch-0.1.0.tar.gz
| Download URL | mcp_patch-0.1.0.tar.gz |
|---|---|
| Size | 10.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a8b62020365f4c1396ac973ac1697e1f9ee1ad37acbc8589e04f08612410b25
|
|
BLAKE2b-256 checksum How to use checksums |
d4cae3ca49760bb7e47ca1e4e43054335decf5b96da46103957709953e79ab0e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Release files / mcp_patch-0.1.0-py3-none-any.whl
| Download URL | mcp_patch-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
67d0fb560721e1d077eb881ba49d0d899042d85614fbf31d74dfb74975dc3396
|
|
BLAKE2b-256 checksum How to use checksums |
87f722449b6075345eeefe74ff608ad8ac0ca0f4b51f3d8815f20c1620a80998
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Security for mcp-patch 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.