Feb 27, 2026·5 min read·51 visits
The MCP Go SDK used Go's standard `encoding/json`, which happily accepts `Method` instead of `method`. Security tools (WAFs) often expect strict JSON-RPC compliance and only block `method`. This mismatch allows attackers to bypass filters by simply capitalizing JSON keys.
A high-severity interpretation conflict in the Model Context Protocol (MCP) Go SDK allows attackers to bypass security intermediaries. By exploiting Go's standard library JSON parsing behavior, which is case-insensitive by default, attackers can smuggle malicious payloads past WAFs that strictly adhere to the case-sensitive JSON-RPC 2.0 specification.
In the world of secure coding, "robustness" is often a double-edged sword. We are taught Postel's Law: "be conservative in what you do, be liberal in what you accept from others." But in security, being liberal is just another way of saying "please exploit me."
The Model Context Protocol (MCP) is the new connective tissue for LLMs, allowing AI models to talk to local tools and servers. The Go SDK (modelcontextprotocol/go-sdk) is the standard implementation for Go developers building these tools. You'd expect it to follow the JSON-RPC 2.0 spec to the letter. The spec is clear: field names are case-sensitive.
However, the Go SDK developers made a fatal, yet common, mistake: they trusted the standard library. Go's encoding/json is notoriously friendly. It tries very hard to map JSON keys to struct fields, ignoring case differences if an exact match isn't found. While this is great for developer velocity, it creates a massive "Interpretation Conflict" (CWE-436) when placed behind a security intermediary that actually follows the rules.
The vulnerability lies in how different systems interpret the same data stream. This is a classic semantic gap. On one side, you have a WAF or a sidecar proxy. These security devices are typically configured to be fast and pedantic. If the rule says block method: "exec", they look for those exact bytes. They assume that Method: "exec" is invalid JSON-RPC and ignore it, or let it pass because it doesn't match the blocklist.
On the other side, you have the vulnerable MCP Go SDK. It defines its request structures with standard Go tags:
type Request struct {
Method string `json:"method"`
// ... other fields
}When json.Unmarshal sees a JSON payload like {"Method": "..."}, it looks for a struct field named Method. It finds it. It checks the tag json:"method". It notices the case doesn't match, but because Go is "helpful," it says, "Eh, close enough," and populates the field anyway.
This behavior violates the JSON-RPC 2.0 specification, which explicitly states that member names are case-sensitive. The SDK was accepting malformed protocol messages that were semantically valid to the Go runtime but syntactically invalid to the protocol spec.
The fix required a fundamental shift in how the SDK handles JSON. You can't just tell the standard encoding/json to stop being case-insensitive; it's hardcoded behavior. The maintainers had to rip out the standard library and replace it with segmentio/encoding/json, a third-party library that offers more granular control.
Here is the critical change in internal/json/json.go. Notice the explicit disable switch:
// BEFORE: Using standard library (implicit in other files)
// err := json.Unmarshal(data, &v)
// AFTER: Using segmentio with case-sensitivity enforced
func Unmarshal(data []byte, v any) error {
dec := json.NewDecoder(bytes.NewReader(data))
// This line kills the vulnerability
dec.DontMatchCaseInsensitiveStructFields()
return dec.Decode(v)
}The patch (Commit 7b8d81c264074404abdf5aa16e2cf0c2d9c64cc0) introduces this wrapper and replaces all calls to json.Unmarshal throughout the codebase (mcp/client.go, mcp/server.go, etc.). It forces the parser to be pedantic: if the JSON key is Method but the struct tag expects method, the field is ignored (left zero-valued), or the parsing fails depending on validation logic.
Let's construct a real-world attack scenario. Imagine an MCP server exposing a sensitive tool, say filesystem/write. A security proxy sits in front of it, configured to allow filesystem/read but block filesystem/write.
The WAF rule might look something like this (pseudocode):
rule:
match:
json_key: "method"
value: "filesystem/write"
action: BLOCKThe Attack Chain:
Normal Request (Blocked):
The attacker sends valid JSON-RPC:
{"jsonrpc": "2.0", "method": "filesystem/write", "params": {...}}
The WAF sees method matches the blocklist. Request Dropped.
Bypass Request (Allowed):
The attacker capitalizes the key:
{"jsonrpc": "2.0", "Method": "filesystem/write", "params": {...}}
The WAF parses the JSON. It looks for the key method. It does not find it (it sees Method). It assumes this is a non-standard field or simply not the field it's watching. It forwards the request.
Execution:
The Go SDK receives the payload. json.Unmarshal matches Method (JSON) to Method (Struct). The handler for filesystem/write is invoked. The file is overwritten.
This is a textbook HTTP Request Smuggling attack, but adapted for the JSON-RPC application layer.
The mitigation is straightforward but requires a dependency change. If you are using modelcontextprotocol/go-sdk, you must upgrade to version 1.3.1 immediately. This version enforces strict case matching, aligning the Go implementation with the JSON-RPC 2.0 spec and other language implementations (like TypeScript).
If you cannot upgrade immediately, your defense-in-depth strategy needs a patch. You must reconfigure your WAFs and proxies to inspect all case variations of the method key. However, this is a losing battle. Can you guarantee your WAF will catch mEthod, METHOD, and Method? What about id vs ID?
This vulnerability serves as a reminder: when implementing strict protocols, do not rely on standard libraries that prioritize developer experience over specification compliance. Explicitly validate input, or use parsers that allow you to turn off "fuzzy" matching features.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
go-sdk modelcontextprotocol | < 1.3.1 | 1.3.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-436 (Interpretation Conflict) |
| Secondary CWE | CWE-178 (Improper Handling of Case Sensitivity) |
| CVSS v4.0 | 7.0 (High) |
| Attack Vector | Network (AV:N) |
| EPSS Score | 0.00048 (Low Probability) |
| Impact | Security Bypass (Subsequent System Integrity) |
A vulnerability in the Slack and Mattermost platform adapters for NousResearch hermes-agent permits an unauthenticated remote attacker to execute arbitrary mass mentions. By leveraging prompt injection, an attacker can bypass output sanitization logic and trigger workspace-wide notification exhaustion.
CVE-2026-9306 is a critical unauthenticated Insecure Direct Object Reference (IDOR) vulnerability located in the QuantumNous new-api application, affecting versions up to and including 0.12.1. The flaw is caused by improper middleware ordering combined with a lack of object-level authorization checks. This allows remote, unauthenticated attackers to retrieve sensitive Midjourney images belonging to other users by supplying a valid task identifier.
The instagrapi library prior to version 2.6.9 contains an improper input validation vulnerability within its challenge handling mechanism. Maliciously crafted server responses can manipulate the client into forwarding session cookies and credentials to an external attacker-controlled domain.
GHSA-QQQM-5547-774X is a critical path traversal vulnerability in the FileBrowser Quantum application, specifically within the Go backend package. The vulnerability resides in the HTTP handler responsible for processing bulk file modifications via the public API. Unauthenticated attackers can exploit an order-of-operations flaw in the path sanitization logic to bypass intended directory restrictions. This allows adversaries to arbitrarily read, move, and overwrite files on the underlying filesystem by supplying specially crafted HTTP PATCH requests.
The qs query string parsing and serialization library for Node.js is vulnerable to a synchronous Denial of Service (DoS) attack. The vulnerability manifests as a process-terminating TypeError when processing arrays with null or undefined elements under specific configuration parameters.
The aiosend library prior to version 3.0.6 contains a pre-authentication Denial of Service (DoS) vulnerability in its webhook handling mechanism. The software processes and deserializes incoming JSON payloads before verifying the cryptographic signature, allowing unauthenticated attackers to exhaust server CPU and memory resources by sending large, complex payloads.