In SSE/HTTP transport mode, mysql_mcp_server constructs SseServerTransport without passing security_settings. 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: MCP_TRANSPORT=sse. The default stdio mode is not affected.
Scenario A — Direct exposure: Any network attacker can invoke execute_sql 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 execute_sql as same-origin.
In src/mysql_mcp_server/server.py:
SseServerTransport is constructed without security_settings — the SDK defaults enable_dns_rebinding_protection to False./, /sse, /messages/) are unauthenticated.0.0.0.0 by default.cursor.execute(query) with a fully attacker-controlled query.FILE privilege: arbitrary file read (LOAD_FILE) and write (INTO OUTFILE) — potential RCE via webshell dropReleased in v0.4.2: DNS-rebinding protection is now enabled by passing TransportSecuritySettings(enable_dns_rebinding_protection=True) to SseServerTransport, and the documented recommended bind address is 127.0.0.1.
Discovered by Huanchen, SongWu (JHU), and BrookeYangRui (JHU).
{
"cwe_ids": [
"CWE-306",
"CWE-346"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-11T20:35:42Z",
"nvd_published_at": null,
"severity": "CRITICAL"
}