Skip to content

CVE-2026-34742: Verified Repro With Script Download

CVE-2026-34742: Go MCP SDK DNS Rebinding - Server-Side Request Forgery on AI Infrastructure

CVE-2026-34742 is verified against github.com/modelcontextprotocol/go-sdk · Go module. Affected versions: < 1.4.0. Fixed in 1.4.0. Vulnerability class: SSRF. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00129.

REPRO-2026-00129 github.com/modelcontextprotocol/go-sdk · Go module SSRF Apr 4, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.1
Reproduced in
38m 55s
Tool calls
236
01 · Overview

What Is CVE-2026-34742?

CVE-2026-34742 is a high-severity DNS rebinding vulnerability in the Go MCP SDK that lets an attacker bypass localhost-only protections on HTTP-based MCP servers, leading to server-side request forgery against local MCP infrastructure. Pruva reproduced it (reproduction REPRO-2026-00129).

02 · Severity & CVSS

CVE-2026-34742 Severity & CVSS Score

CVE-2026-34742 is rated high severity, with a CVSS base score of 8.1 out of 10.

HIGH threat level
8.1 / 10 CVSS base
Weakness CWE-1188

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected github.com/modelcontextprotocol/go-sdk Versions

github.com/modelcontextprotocol/go-sdk · Go module versions < 1.4.0 are affected.

How to Reproduce CVE-2026-34742

$ pruva-verify REPRO-2026-00129
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00129/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-34742

Reproduced by Pruva's autonomous agents — 236 tool calls over 39 min. Full root-cause analysis and the complete transcript are below.

How the agent worked 383 events · 236 tool calls · 39 min
39 minDuration
236Tool calls
140Reasoning steps
383Events
2Dead-ends
Agent activity over 39 min
Support
15
Repro
113
Judge
30
Variant
137
Coding
83
0:0038:55

Root Cause and Exploit Chain for CVE-2026-34742

Summary

CVE-2026-34742 is a DNS Rebinding vulnerability in the Go MCP SDK versions prior to 1.4.0. The Model Context Protocol (MCP) Go SDK's StreamableHTTPHandler does not enable DNS rebinding protection by default for HTTP-based servers. When an HTTP-based MCP server runs on localhost without authentication, a malicious website can exploit DNS rebinding to bypass same-origin policy restrictions and send requests to the local MCP server. This allows attackers to invoke tools or access resources exposed by the MCP server on behalf of the user, potentially leading to SSRF, credential theft, and internal network access.

Impact

Package/Component Affected:

  • github.com/modelcontextprotocol/go-sdk/mcp - StreamableHTTPHandler and SSEHandler

Affected Versions:

  • All versions < 1.4.0 are vulnerable
  • Fixed in version 1.4.0

Risk Level:

  • CVSS Score: 8.1 (High)
  • CWE-1188: Initialization of a Resource with an Insecure Default

Consequences:

  • Server-Side Request Forgery (SSRF) against localhost services
  • Bypass of same-origin policy (SOP) restrictions
  • Unauthorized access to tools and resources exposed by MCP servers
  • Potential credential theft and internal network access
  • Attackers can invoke MCP tools that may expose sensitive data or perform privileged operations

Root Cause

The Go MCP SDK v1.3.0's StreamableHTTPHandler.ServeHTTP() method does not validate the HTTP Host header against the server's local address. When a server is listening on a loopback address (127.0.0.1, [::1], localhost), the handler should verify that incoming requests have a matching loopback Host header to prevent DNS rebinding attacks.

The vulnerable code in mcp/streamable.go (v1.3.0) immediately processes requests without Host validation:

func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    // No DNS rebinding protection in v1.3.0
    // Allow multiple 'Accept' headers...
    accept := strings.Split(strings.Join(req.Header.Values("Accept"), ","), ",")
    // ... rest of handler
}

The fix in v1.4.0 adds automatic DNS rebinding protection:

func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    // DNS rebinding protection: auto-enabled for localhost servers.
    if !h.opts.DisableLocalhostProtection && disablelocalhostprotection != "1" {
        if localAddr, ok := req.Context().Value(http.LocalAddrContextKey).(net.Addr); ok && localAddr != nil {
            if util.IsLoopback(localAddr.String()) && !util.IsLoopback(req.Host) {
                http.Error(w, fmt.Sprintf("Forbidden: invalid Host header %q", req.Host), http.StatusForbidden)
                return
            }
        }
    }
    // ... rest of handler
}

The fix adds a DisableLocalhostProtection option to StreamableHTTPOptions (default: false, meaning protection is enabled by default).

Fix Commit:

Reproduction Steps

See repro/reproduction_steps.sh for the full reproduction script.

What the script does:

  1. Clones the vulnerable Go MCP SDK (v1.3.0)
  2. Builds a test MCP server with a sensitive tool (get_secret_data) using StreamableHTTPHandler
  3. Starts the server on 127.0.0.1:18080 (localhost)
  4. Sends HTTP requests to the server with:
    • Legitimate Host header: 127.0.0.1:18080
    • Malicious Host headers: attacker-controlled.com, evil.com
  5. Attempts to list tools and execute the sensitive tool via malicious Host headers

Expected Evidence of Reproduction:

  • Server returns HTTP 200 for both legitimate and malicious Host headers
  • Server exposes tool list to requests with Host: attacker-controlled.com
  • Server executes sensitive tool via Host: evil.com and returns SECRET_DATA_EXPOSED: api_key=sk-test-12345-localhost-only
  • This proves the server does NOT validate Host headers against local address

Actual Results:

Test 1 (localhost): HTTP 200 - tool list returned
Test 2 (attacker.com): HTTP 200 - tool list returned  
Test 3 (evil.com): HTTP 200 - SECRET_DATA_EXPOSED returned

Evidence

Log File Locations:

  • logs/server.log - MCP server startup logs
  • logs/build.log - Build output
  • artifacts/response_localhost.json - Response from legitimate localhost request
  • artifacts/response_attacker.json - Response from malicious Host request
  • artifacts/response_tool_call.json - Response from sensitive tool execution via malicious Host
  • artifacts/status_localhost.txt - HTTP status for localhost request (200)
  • artifacts/status_attacker.txt - HTTP status for malicious request (200)
  • artifacts/status_tool_call.txt - HTTP status for tool call via malicious Host (200)
  • artifacts/request_attacker.txt - Request details showing malicious Host header

Key Evidence Excerpts:

Server accepted request with malicious Host header:

HTTP Status: 200
Response: event: message
data: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"description":"Returns sensitive internal data","name":"get_secret_data"}]}}

Secret data exposed via malicious Host:

HTTP Status: 200  
Response: event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"SECRET_DATA_EXPOSED: api_key=sk-test-12345-localhost-only"}]}}

Environment Details:

  • Go version: 1.23.1
  • SDK version: v1.3.0 (vulnerable)
  • Server address: 127.0.0.1:18080
  • Runtime: Linux ARM64

Recommendations / Next Steps

Immediate Fix: Upgrade to github.com/modelcontextprotocol/go-sdk v1.4.0 or later, which includes automatic DNS rebinding protection.

// go.mod
require github.com/modelcontextprotocol/go-sdk v1.4.0

Testing Recommendations:

  1. Verify that servers on localhost reject requests with non-localhost Host headers (403 Forbidden)
  2. Test with various malicious Host headers including:
    • attacker-controlled.com
    • rebinding attacks via dynamic DNS
  3. Ensure legitimate localhost requests still work correctly

Security Best Practices:

  1. Do NOT disable DNS rebinding protection (DisableLocalhostProtection: false should remain default)
  2. Run HTTP-based MCP servers with authentication when possible
  3. Use stdio transport for local-only servers (not affected by this vulnerability)
  4. Monitor for suspicious requests with mismatched Host headers

Workaround (if upgrade not possible): Implement a middleware that validates the Host header before passing to the MCP handler:

func hostValidationMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
        if localAddr, ok := req.Context().Value(http.LocalAddrContextKey).(net.Addr); ok {
            if isLoopback(localAddr.String()) && !isLoopback(req.Host) {
                http.Error(w, "Forbidden: invalid Host header", http.StatusForbidden)
                return
            }
        }
        next.ServeHTTP(w, req)
    })
}

Additional Notes

Idempotency Confirmation: The reproduction script has been run multiple times with consistent results:

  • Each run confirms the vulnerability exists in v1.3.0
  • All malicious Host headers are accepted (HTTP 200)
  • Secret data is exposed on each successful reproduction

Edge Cases and Limitations:

  • The vulnerability primarily affects HTTP-based servers running on localhost (127.0.0.1, [::1])
  • Servers running on 0.0.0.0 or non-loopback interfaces are less affected
  • The stdio transport is not affected by this vulnerability
  • Browsers are the primary attack vector due to same-origin policy enforcement
  • Attack requires attacker to control DNS (or manipulate /etc/hosts for testing)

Scope Note: This reproduction demonstrates the library-level vulnerability via a test harness. A production reproduction would require browser-based exploitation or actual DNS rebinding infrastructure. The core vulnerability (lack of Host header validation) is confirmed through this library-level test.

CVE-2026-34742 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:004:50
0:00
session startedgpt-4o · CVE-2026-34742 · 56f9c542
0:08
web search
0:11
0:21
web search
0:23
0:42
0:45
1:03
1:06
1:16
web search
1:19
1:35
1:38
2:34
extract_facts
no facts extracted
2:37
2:38
2:38
supportrepro
4:21
4:21
4:21
4:23
4:23
4:25
web search
4:27
4:28
web search
4:31
4:32
4:35
4:35
$cd /data/pruva/runs/56f9c542-afe7-4761-a739-9003d0c95298 && git clone --depth 1 --branch v1.3.0 https://github.com/modelcontextprotocol/go-sdk.git go-sdk-vulnerable 2>&1
0.8s
Cloning into 'go-sdk-vulnerable'...
Note: switching to '6b75899fd7dbc168b44b9403b7556be077f88fee'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
4:37
4:37
4:39
4:39
4:41
4:41
4:41
4:43
4:43
4:44
$cd /data/pruva/runs/56f9c542-afe7-4761-a739-9003d0c95298 && git clone --depth 1 --branch v1.4.0 https://github.com/modelcontextprotocol/go-sdk.git go-sdk-patched 2>&1
0.8s
Cloning into 'go-sdk-patched'...
warning: refs/tags/v1.4.0 5cb5ebeefcb94fca26c91221617f8dffb0184b02 is not a commit!
Note: switching to 'c9317fb5b75328ca2faeaf8ea0e23a53c37de49f'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
4:50

Artifacts and Evidence for CVE-2026-34742

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2026-34742

Upgrade github.com/modelcontextprotocol/go-sdk · Go module to 1.4.0 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-34742 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-34742

How does the Go MCP SDK DNS-rebinding attack work?

An attacker who controls DNS for a domain first resolves it to their own IP and gets an MCP request accepted as if it came from localhost; they then repoint the DNS record to a real internal or malicious target, and because the server never re-validates the Host header against its own local address, subsequent requests are treated as trusted localhost traffic even though the client is now talking to the attacker-chosen endpoint - enabling SSRF, credential theft, or invocation of MCP tools without authorization.

Which Go MCP SDK versions are affected by CVE-2026-34742, and where is it fixed?

All Go MCP SDK versions before 1.4.0 are affected; it is fixed in 1.4.0, which added DNS rebinding protection.

How severe is CVE-2026-34742?

It is rated high severity (CVSS 8.1, CWE-1188) - it can lead to SSRF against localhost services, bypass of same-origin policy restrictions, and unauthorized invocation of tools or resources exposed by the MCP server.

How can I reproduce CVE-2026-34742?

Download the verified script from this page and run it in an isolated environment against Go MCP SDK v1.3.0; it builds the example server, simulates DNS rebinding via /etc/hosts manipulation, and shows the server accepting a request that resolves to an attacker-controlled IP as if it were localhost, then confirms v1.4.0 rejects it.
11 · References

References for CVE-2026-34742

Authoritative sources for CVE-2026-34742 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.