Every CVE Search/ Get API key

CVE-2026-63118

MCP Ruby SDK: Streamable HTTP transport lacks DNS-rebinding (Host/Origin) protection

6.9 MediumFix available

MCP Ruby SDK is the official Ruby SDK for Model Context Protocol servers and clients. Prior to 0.23.0, MCP::Server::Transports::StreamableHTTPTransport in the mcp gem does not validate the HTTP Host or Origin request headers, which allows a malicious browser page to use DNS rebinding to reach a locally running MCP server and invoke exposed tools. This issue is fixed in version 0.23.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
Active

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.24%Unchanged since Jul 30, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.9

MCP Ruby SDK: Streamable HTTP transport lacks DNS-rebinding (Host/Origin) protection

MCP Ruby SDK is the official Ruby SDK for Model Context Protocol servers and clients. Prior to 0.23.0, MCP::Server::Transports::StreamableHTTPTransport in the mcp gem does not validate the HTTP Host or Origin request headers, which allows a malicious browser page to use DNS rebinding to reach a locally running MCP server and invoke exposed tools. This issue is fixed in version 0.23.0.

Record
CVE-2026-63118
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-346, CWE-350
Updated
2026-11-02
EUVDEUVD-2026-50489 6.9

MCP Ruby SDK is the official Ruby SDK for Model Context Protocol servers and clients. Prior to 0.23.0, MCP::Server::Transports::StreamableHTTPTransport in the mcp gem does not validate the HTTP Host or Origin request headers, which allows a malicious browser page to use DNS rebinding to reach a locally running MCP server and invoke exposed tools. This issue is fixed in version 0.23.0.

Record
EUVD-2026-50489
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-rjr6-rcgv-9m7m 6.9

MCP Ruby SDK: Streamable HTTP transport lacks DNS-rebinding (Host/Origin) protection

Summary

MCP::Server::Transports::StreamableHTTPTransport (the Rack-mountable Streamable HTTP transport in the mcp gem) processes every incoming JSON-RPC request without ever inspecting the HTTP Host or Origin request headers. There is no AllowedHosts/AllowedOrigins allowlist and no DNS-rebinding guard anywhere in the transport. A local MCP server that binds a loopback or LAN HTTP port is therefore reachable by any web origin a victim's browser visits, via a DNS-rebinding attack: a malicious page rebinds its own hostname to 127.0.0.1, then drives the local MCP server cross-origin to enumerate and invoke its tools and exfiltrate their output. This is the standard browser-driven local-service attack that the MCP Streamable HTTP guidance exists to prevent.

Impact

  • An attacker who can get a victim to open a web page can reach any MCP server the victim runs locally over the Streamable HTTP transport (e.g. a developer-tools or filesystem MCP server on localhost).
  • Because the transport issues a session and dispatches tools/list / tools/call from a foreign Host/Origin with no rejection, the attacker can drive arbitrary server-exposed tools and read their results, exfiltrating local data (files, secrets, command output) to the attacker's origin.
  • The blast radius is whatever the locally-running MCP server exposes. For MCP servers wired to filesystem, shell, or credential tools, this is sensitive-data disclosure and, depending on the tool set, local action execution.

Vulnerable code

File: lib/mcp/server/transports/streamable_http_transport.rb (gem mcp 0.18.0).

The Rack entrypoint and POST handler validate Accept, Content-Type, Mcp-Session-Id, and Mcp-Protocol-Version, but never Host or Origin:

# call(env) -> handle_request(Rack::Request.new(env))  (line 56)
def handle_post(request)
  required_types = @enable_json_response ? REQUIRED_POST_ACCEPT_TYPES_JSON : REQUIRED_POST_ACCEPT_TYPES_SSE
  accept_error = validate_accept_header(request, required_types)   # line 335 - checks Accept only
  return accept_error if accept_error

  content_type_error = validate_content_type(request)             # line 338 - checks Content-Type only
  return content_type_error if content_type_error

  body_string = request.body.read
  session_id = extract_session_id(request)                        # line 342 - reads HTTP_MCP_SESSION_ID

No statement anywhere in handle_post, handle_request, or any helper reads request.env["HTTP_HOST"] or request.env["HTTP_ORIGIN"].

The only request-env reads in the whole class are:

  • extract_session_id -> request.env["HTTP_MCP_SESSION_ID"] (line 489)
  • validate_accept_header -> request.env["HTTP_ACCEPT"] (line 493)
  • validate_content_type -> request.env["CONTENT_TYPE"] (line 512)
  • validate_protocol_version_header -> request.env["HTTP_MCP_PROTOCOL_VERSION"] (line 546)

A repository-wide search of lib/ for HTTP_HOST, HTTP_ORIGIN, allowed_host, allowed_origin, rebind, or dns.rebind returns zero matches, confirming no allowlist or rebinding guard exists in the shipped library. The examples/ tree mounts Rack::Cors as application-level middleware, but that is example glue, not a transport-level control, and CORS does not stop a DNS-rebinding attack that arrives as a same-origin request after rebinding.

How the input reaches the sink (attack scenario)

  1. A developer runs an MCP server over StreamableHTTPTransport, mounted as a Rack app on a local HTTP port (loopback or LAN).
  2. The victim opens http://evil.attacker.com in a browser. The page resolves to the attacker's server, which then re-answers DNS for evil.attacker.com with 127.0.0.1 (DNS rebinding). The browser now treats requests to evil.attacker.com as going to the local MCP server, with Host: evil.attacker.com / Origin: http://evil.attacker.com.
  3. The page POSTs an initialize request. The transport accepts it (it never looks at…
Record
GHSA-rjr6-rcgv-9m7m
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-346, CWE-350
Updated
2026-11-02
NVD 6.9

MCP Ruby SDK is the official Ruby SDK for Model Context Protocol servers and clients. Prior to 0.23.0, MCP::Server::Transports::StreamableHTTPTransport in the mcp gem does not validate the HTTP Host or Origin request headers, which allows a malicious browser page to use DNS rebinding to reach a locally running MCP server and invoke exposed tools. This issue is fixed in version 0.23.0.

Record
CVE-2026-63118
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-346, CWE-350
Updated
2026-11-02
OSV 6.9

MCP Ruby SDK: Streamable HTTP transport lacks DNS-rebinding (Host/Origin) protection

MCP Ruby SDK is the official Ruby SDK for Model Context Protocol servers and clients. Prior to 0.23.0, MCP::Server::Transports::StreamableHTTPTransport in the mcp gem does not validate the HTTP Host or Origin request headers, which allows a malicious browser page to use DNS rebinding to reach a locally running MCP server and invoke exposed tools. This issue is fixed in version 0.23.0.

Record
CVE-2026-63118
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-346, CWE-350
Updated
2026-11-02
OSVGHSA-rjr6-rcgv-9m7m 6.9

MCP Ruby SDK: Streamable HTTP transport lacks DNS-rebinding (Host/Origin) protection

Summary

MCP::Server::Transports::StreamableHTTPTransport (the Rack-mountable Streamable HTTP transport in the mcp gem) processes every incoming JSON-RPC request without ever inspecting the HTTP Host or Origin request headers. There is no AllowedHosts/AllowedOrigins allowlist and no DNS-rebinding guard anywhere in the transport. A local MCP server that binds a loopback or LAN HTTP port is therefore reachable by any web origin a victim's browser visits, via a DNS-rebinding attack: a malicious page rebinds its own hostname to 127.0.0.1, then drives the local MCP server cross-origin to enumerate and invoke its tools and exfiltrate their output. This is the standard browser-driven local-service attack that the MCP Streamable HTTP guidance exists to prevent.

Impact

  • An attacker who can get a victim to open a web page can reach any MCP server the victim runs locally over the Streamable HTTP transport (e.g. a developer-tools or filesystem MCP server on localhost).
  • Because the transport issues a session and dispatches tools/list / tools/call from a foreign Host/Origin with no rejection, the attacker can drive arbitrary server-exposed tools and read their results, exfiltrating local data (files, secrets, command output) to the attacker's origin.
  • The blast radius is whatever the locally-running MCP server exposes. For MCP servers wired to filesystem, shell, or credential tools, this is sensitive-data disclosure and, depending on the tool set, local action execution.

Vulnerable code

File: lib/mcp/server/transports/streamable_http_transport.rb (gem mcp 0.18.0).

The Rack entrypoint and POST handler validate Accept, Content-Type, Mcp-Session-Id, and Mcp-Protocol-Version, but never Host or Origin:

# call(env) -> handle_request(Rack::Request.new(env))  (line 56)
def handle_post(request)
  required_types = @enable_json_response ? REQUIRED_POST_ACCEPT_TYPES_JSON : REQUIRED_POST_ACCEPT_TYPES_SSE
  accept_error = validate_accept_header(request, required_types)   # line 335 - checks Accept only
  return accept_error if accept_error

  content_type_error = validate_content_type(request)             # line 338 - checks Content-Type only
  return content_type_error if content_type_error

  body_string = request.body.read
  session_id = extract_session_id(request)                        # line 342 - reads HTTP_MCP_SESSION_ID

No statement anywhere in handle_post, handle_request, or any helper reads request.env["HTTP_HOST"] or request.env["HTTP_ORIGIN"].

The only request-env reads in the whole class are:

  • extract_session_id -> request.env["HTTP_MCP_SESSION_ID"] (line 489)
  • validate_accept_header -> request.env["HTTP_ACCEPT"] (line 493)
  • validate_content_type -> request.env["CONTENT_TYPE"] (line 512)
  • validate_protocol_version_header -> request.env["HTTP_MCP_PROTOCOL_VERSION"] (line 546)

A repository-wide search of lib/ for HTTP_HOST, HTTP_ORIGIN, allowed_host, allowed_origin, rebind, or dns.rebind returns zero matches, confirming no allowlist or rebinding guard exists in the shipped library. The examples/ tree mounts Rack::Cors as application-level middleware, but that is example glue, not a transport-level control, and CORS does not stop a DNS-rebinding attack that arrives as a same-origin request after rebinding.

How the input reaches the sink (attack scenario)

  1. A developer runs an MCP server over StreamableHTTPTransport, mounted as a Rack app on a local HTTP port (loopback or LAN).
  2. The victim opens http://evil.attacker.com in a browser. The page resolves to the attacker's server, which then re-answers DNS for evil.attacker.com with 127.0.0.1 (DNS rebinding). The browser now treats requests to evil.attacker.com as going to the local MCP server, with Host: evil.attacker.com / Origin: http://evil.attacker.com.
  3. The page POSTs an initialize request. The transport accepts it (it never looks at…
Record
GHSA-rjr6-rcgv-9m7m
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-346, CWE-350
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
mcp
RubyGems
through 0.22.0
0.23.0
mcp
RubyGems
before 0.23.0, plus listed versions
0.1.00.10.00.11.00.12.00.13.0
Show 20 moreShow less
0.14.00.15.00.16.00.17.00.18.00.19.00.2.00.20.00.21.00.22.00.3.00.4.00.5.00.6.00.7.00.7.10.8.00.9.00.9.10.9.2
0.23.0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-63118 is a medium vulnerability (CVSS 6.9) in Modelcontextprotocol Ruby-sdk, published July 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.24%, the 15th percentile. Fixed in mcp 0.23.0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open