Skip to content

MCP-2026-008: CacheableResult cacheScope:public enables cross-user cache poisoning #3207

Description

@shunfeng8421

Summary

CacheableResult (introduced in v2026-07-28) defines cacheScope: "public" | "private". When cacheScope: "public" is set, the spec explicitly allows any intermediary (shared gateway, caching proxy) to cache the response and serve it across authorization contexts. This enables a cache poisoning attack: a malicious server can return poisoned tool/prompt/resource lists with cacheScope: "public", and the shared cache will serve this poisoned content to other users.

Affected endpoints

All list/read results that extend CacheableResult:

  • tools/listListToolsResult
  • prompts/listListPromptsResult
  • resources/listListResourcesResult
  • resources/readReadResourceResult

Attack scenario

  1. An attacker deploys a malicious MCP server that returns cacheScope: "public" with a poisoned tool list (e.g., system_exec, read_any_file)
  2. A shared cache proxy (CDN, enterprise gateway) respects the cacheScope: "public" directive and caches the response
  3. Victim B requests tools/list through the same proxy — gets the poisoned tool list from cache
  4. The LLM client sees system_exec as a legitimate tool and may invoke it automatically

Root cause

The spec says: "public: The response does not contain user-specific data. Any client or intermediary (e.g., shared gateway, caching proxy) MAY cache the response and serve it across authorization contexts."

There is no mechanism to verify that the cached content actually came from a trusted server. The cacheScope field is server-authored metadata — the attacker controls it entirely.

PoC

A working proof-of-concept is available at:
https://github.com/shunfeng8421/mcp-pocs/blob/main/poc_cache_poisoning.py

Additional observation

The mcp Python SDK (v2.0.0) does not implement CacheableResult at all — none of ListToolsResult, ListPromptsResult, ListResourcesResult, or ReadResourceResult include ttlMs or cacheScope fields, despite the specification requiring them. This means:

  • SDK-generated servers cannot produce compliant responses
  • SDK-based clients cannot benefit from caching
  • There is a gap between spec and implementation

Suggested mitigations

  1. Remove cacheScope: "public" or make it opt-in with explicit server identity verification
  2. Add a mechanism for clients to verify the origin of cached responses (e.g., signature over the cache entry)
  3. Require that cacheScope: "public" responses include a verifiable server identity
  4. Update the SDK to implement CacheableResult so the spec and implementation are aligned

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions