Skip to main content

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)

Source distribution for mcp-patch 0.1.0
File Size Uploaded
mcp_patch-0.1.0.tar.gz 10.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-patch 0.1.0
File Interpreter ABI Platform
mcp_patch-0.1.0-py3-none-any.whl Python 3 none any Details

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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page