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.
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).
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 — serious impact or readily exploitable. Prioritize remediation.
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 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00129/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh 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
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:
- https://github.com/modelcontextprotocol/go-sdk/releases/tag/v1.4.0
- GitHub Security Advisory: GHSA-xw59-hvm2-8pj6
Reproduction Steps
See repro/reproduction_steps.sh for the full reproduction script.
What the script does:
- Clones the vulnerable Go MCP SDK (v1.3.0)
- Builds a test MCP server with a sensitive tool (
get_secret_data) using StreamableHTTPHandler - Starts the server on 127.0.0.1:18080 (localhost)
- Sends HTTP requests to the server with:
- Legitimate Host header:
127.0.0.1:18080 - Malicious Host headers:
attacker-controlled.com,evil.com
- Legitimate Host header:
- 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.comand returnsSECRET_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 logslogs/build.log- Build outputartifacts/response_localhost.json- Response from legitimate localhost requestartifacts/response_attacker.json- Response from malicious Host requestartifacts/response_tool_call.json- Response from sensitive tool execution via malicious Hostartifacts/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:
- Verify that servers on localhost reject requests with non-localhost Host headers (403 Forbidden)
- Test with various malicious Host headers including:
- attacker-controlled.com
- rebinding attacks via dynamic DNS
- Ensure legitimate localhost requests still work correctly
Security Best Practices:
- Do NOT disable DNS rebinding protection (
DisableLocalhostProtection: falseshould remain default) - Run HTTP-based MCP servers with authentication when possible
- Use stdio transport for local-only servers (not affected by this vulnerability)
- 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.
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>&1Cloning 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
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>&1Cloning 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.
Artifacts and Evidence for CVE-2026-34742
Scripts, logs, diffs, and output captured during the reproduction.
No artifacts available
How to Fix CVE-2026-34742
Upgrade github.com/modelcontextprotocol/go-sdk · Go module to 1.4.0 or later.
FAQ: CVE-2026-34742
How does the Go MCP SDK DNS-rebinding attack work?
Which Go MCP SDK versions are affected by CVE-2026-34742, and where is it fixed?
How severe is CVE-2026-34742?
How can I reproduce CVE-2026-34742?
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.