GHSA-rqfv-2mw9-78g2: Critical severity pip/mysql-mcp-server vulnerability
Summary
In SSE/HTTP transport mode, mysqlmcpserver constructs SseServerTransport without passing securitysettings. As a result, the MCP Python SDK's DNS-rebinding protection (Origin/Host header validation) is disabled; the Starlette application has no CORS or TrustedHost middleware; and the service binds to 0.0.0.0 by default with no authentication on any route.
Trigger condition: MCPTRANSPORT=sse. The default stdio mode is not affected.
Attack Scenarios
Scenario A — Direct exposure: Any network attacker can invoke executesql to run arbitrary SQL without credentials → full data dump, and via MySQL FILE privileges, arbitrary file read/write and RCE.
Scenario B — DNS rebinding (local bind): An attacker lures a victim's browser to a malicious page, rebinds their domain to 127.0.0.1, and uses the browser as a proxy to invoke executesql as same-origin.
Root Cause
In src/mysqlmcpserver/server.py:
1. SseServerTransport is constructed without securitysettings — the SDK defaults enablednsrebindingprotection to False. 2. The Starlette app has no CORS or TrustedHost middleware. 3. All three routes (/, /sse, /messages/) are unauthenticated. 4. The service binds to 0.0.0.0 by default. 5. The sink is cursor.execute(query) with a fully attacker-controlled query.
Impact
- Unauthenticated arbitrary SQL execution against the configured database - Full data exfiltration and modification - If the MySQL account holds FILE privilege: arbitrary file read (LOADFILE) and write (INTO OUTFILE) — potential RCE via webshell drop - Internet-wide scanning has identified 25 publicly reachable SSE instances of this project
Fix
Released in v0.4.2: DNS-rebinding protection is now enabled by passing TransportSecuritySettings(enablednsrebindingprotection=True) to SseServerTransport, and the documented recommended bind address is 127.0.0.1.
Credits
Discovered by Huanchen, SongWu (JHU), and BrookeYangRui (JHU).
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/mysql-mcp-serverto a version that resolves this vulnerability.Fixed in 0.4.2 - Upgrade
Upgrade
mysql_mcp_serverto a version that resolves this vulnerability.Fixed in v0.4.2 - Configuration
In SSE/HTTP transport mode, construct `SseServerTransport` with `TransportSecuritySettings(enable_dns_rebinding_protection=True)` so DNS-rebinding protection is enabled (the issue occurs when `SseServerTransport` is constructed without `security_settings`).
SseServerTransport (MCP Python SDK) enable_dns_rebinding_protection = true - Configuration
Add Starlette middleware for CORS and TrustedHost validation (the text states the Starlette app has no CORS or TrustedHost middleware).
Starlette application CORS middleware / TrustedHost middleware = none - Configuration
Change the service bind address from the default `0.0.0.0` to the documented recommended bind address `127.0.0.1` to mitigate the direct exposure/DNS-rebinding attack surface.
MySQL MCP server bind address bind to = 127.0.0.1
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
Deployments using mysql_mcp_server with MCP_TRANSPORT=sse are affected. The default stdio transport mode is not affected; SSE mode binds to 0.0.0.0 by default and exposes unauthenticated routes.
What does an attacker need to exploit the directly exposed service?
A network attacker can invoke execute_sql without credentials when the SSE service is reachable. This enables arbitrary SQL execution, potentially including data disclosure and, where the MySQL account has FILE privileges, arbitrary file read/write and RCE.
Can a service bound only to localhost still be attacked?
Yes. An attacker can use DNS rebinding to cause a victim's browser to access a service at 127.0.0.1 and invoke execute_sql through the browser, because Origin and Host validation are disabled.
How can I determine whether my deployment is affected?
Check whether MCP_TRANSPORT is set to sse. In that mode, the affected application exposes the /, /sse, and /messages/ routes without authentication and lacks the described DNS-rebinding protections.