MCP Went Stateless and Left the Tool Descriptions Alone
The largest MCP revision since launch rewrote the transport and hardened authorization. It says nothing about sanitizing tool descriptions, nothing about a trust boundary around tool metadata, and nothing about provenance. That is a choice worth naming.
I went looking for a tidy article about tool-description poisoning, backed by a run of recent CVEs. The CVEs did not hold up. What I found instead is a better story, and a quieter one.
This post is partly about what the evidence actually supports, because the gap between the two is the interesting part.
The claim that did not survive checking
There is a cluster of 2026 CVEs filed against MCP implementations that gets cited as evidence of tool-description attacks. Three of the most-cited are in the MCP Python SDK, and having read the advisories, none of them involves tool descriptions at all:
| CVE | what it actually is | | --- | --- | | CVE-2026-52869 | Sessions routed on session ID alone, without checking the request came from the principal that created the session | | CVE-2026-52870 | Task handlers operated on task ID with no ownership check, so any client could read another's results | | CVE-2026-59950 | The deprecated WebSocket transport never wired in host and origin validation |
These are real, and two carry CVSS scores above 7. They are transport and authorization bugs. Filing them under "tool poisoning" is how a category gets inflated until it stops meaning anything.
Two Cursor CVEs get pulled into the same pile. Both are path-validation flaws in the sandbox, one a straightforward traversal, the other a canonicalization fallback that lets a symlink escape the workspace. Also real. Also not about tool descriptions.
I am spelling this out because I nearly published the inflated version. The pattern is worth recognising: a search summary aggregates vendor pages, the vendor pages gesture at a category, and the CVE numbers get borrowed to give the category weight it has not earned. The advisories are one click away and they say something different.
The one that is genuinely this
CVE-2026-75130, published 18 August 2026, against Upstash Context7 through version 2.1.2.
Its classification is the notable part: CWE-1427, Improper Neutralization of Input Used for LLM Prompting. That category exists now, and this is what it looks like in the wild.
The description, from the CVE record:
Context7 through 2.1.2 contains a prompt injection vulnerability that allows attackers to execute malicious instructions in connected AI coding agents by injecting unsanitized content through the Custom AI Instructions feature served via the MCP server.
The mechanism: a library owner could attach free text to their library, and that text was served verbatim through the MCP server to every agent that asked about it, mixed in with the legitimate documentation and indistinguishable from it. Demonstrated consequences were reading environment files, exfiltrating credentials to an attacker-controlled service, and deleting files, all triggered by a routine documentation lookup.
Two things to be accurate about, because I have seen both stated wrongly:
The vector is tool output and configuration, not the description field specifically. The payload arrives alongside legitimate documentation through the same channel. That is a close cousin of description poisoning and not identical to it.
The disclosure is not recent. It was found in February 2026, fixed in production within days, and publicly disclosed in March. Only the CVE assignment is dated August. Presenting it as an August incident would be wrong.
The scoring disagreement is its own story
Look at what the two CVSS versions did with the same vulnerability:
| scale | score | | --- | --- | | CVSS 3.1 | 9.0, Critical | | CVSS 4.0 | 6.4, Medium |
A 2.6 point gap and a two-band disagreement on one vulnerability.
This is not an error. It is the two models disagreeing about what matters. Version 3.1 has a scope-change flag, and a compromise that escapes the vulnerable component into the user's machine trips it hard. Version 4.0 splits impact into what happens to the vulnerable system and what happens to subsequent systems, and here the vulnerable-system impacts are all rated none while the subsequent-system impacts are all high.
Which is, if you think about it, exactly right about prompt injection and exactly the wrong shape for a single headline number. The server is unharmed. Everything downstream of it is not. Any severity scale that has to collapse that into one figure is going to mislead somebody, and here it misleads by nearly three points depending on which version your tooling emits.
If you triage on CVSS, this class of vulnerability is where your triage stops working.
What the 2026-07-28 specification did about it
Nothing. I want to be precise rather than rhetorical, so I read the full changelog for the revision.
The security-relevant changes are all in authorization and transport:
- Authorization servers SHOULD include the iss parameter per RFC 9207, and clients MUST validate it before redeeming the authorization code
- Client credentials MUST be keyed by issuer identifier, MUST NOT be reused with a different authorization server, and clients MUST re-register when the authorization server changes
- Dynamic Client Registration requires an appropriate application_type
- Dynamic Client Registration is deprecated in favour of Client ID Metadata Documents
Good changes. Genuinely worth having. Now the absences, which I checked for specifically:
- No requirement to sanitize tool descriptions or tool metadata.
- No trust boundary between tool metadata and model instructions. Nothing says a description is data rather than instruction.
- No provenance or signing mechanism for descriptions. No way for a client to know that the description it received is the one the server author wrote.
The revision that deleted the handshake, removed sessions, restructured server-initiated calls into a retry, deprecated three features and rewrote the authorization rules did not touch the thing that lets a string in a JSON field give instructions to your model.
I do not think that is an oversight. I think it is a hard problem that nobody has a specification-shaped answer to. But the effect is the same either way: MCP still hands tool metadata to a model with the same authority as the system prompt, and the current revision does not say otherwise.
The one number worth quoting, with its caveat
The Cloud Security Alliance's research notes from July 2026 cite the MCPTox benchmark: 20 language models tested against 353 authentic tools from 45 live MCP servers, with an average tool-poisoning attack success rate of 36.5 percent and a high of 72.8 percent against one model.
Caveat, and it matters: that is a 2025 benchmark, and I am citing it via CSA rather than from the paper itself. Treat it as indicative rather than current. It is the best single figure available in this area, which is itself a comment on how thin the measurement is.
The attack class was formally characterised by Invariant Labs in April 2025. Most of the good evidence in this area is from 2025, not 2026, and anyone telling you otherwise is probably counting the transport CVEs.
What you can actually do
The specification does not help you here, so this is on your side of the line.
- Treat every tool description as untrusted input, including from servers you chose. Context7 was not a malicious server; it was a legitimate one with a feature that let third parties write into its output.
- Pin server versions. A description that was fine at install time is not necessarily fine after an update, and nothing in the protocol tells you it changed.
- Diff tool descriptions across updates and alert on changes. This is a few lines of code and it is the single highest-value control available, because it catches the case where a trusted server starts serving different instructions.
- Watch the boundary where third parties can write into tool output. That is the Context7 shape, and it generalises: any server that serves user-contributed content through a tool is a candidate.
- Do not triage this class on a single CVSS number. See above. Read the vector, and specifically the subsequent-system metrics.
The deprecation clock, since it is relevant
The same revision adopted a feature lifecycle policy with a minimum twelve-month deprecation window. There is an expedited path, and its wording is worth knowing: the floor may be shortened when a feature presents an active security risk, defined as a vulnerability with a published security advisory or documented in-the-wild exploitation for which no in-place mitigation exists. Even then the window cannot go below ninety days.
So the process for pulling a dangerous feature exists and it is well specified. It just does not apply here, because tool descriptions are not a deprecated feature. They are the design.