anthropics / anthropics/skills

MCPConnectionSSE / MCPConnectionHTTP accept arbitrary caller-supplied URLs and headers with no validation Affected file: mcp-builder/scripts/connections.py (lines 88–109)

Aperta
#1,621 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Python
Stelle
176k
Fork
20.9k
Merge medio
7h 21m
PR unite (30g)
5

Descrizione

Summary
python
class MCPConnectionSSE(MCPConnection):
"""MCP connection using Server-Sent Events."""

def __init__(self, url: str, headers: dict[str, str] = None):
super().__init__()
self.url = url
self.headers = headers or {}

def _create_context(self):
return sse_client(url=self.url, headers=self.headers)

class MCPConnectionHTTP(MCPConnection):
"""MCP connection using Streamable HTTP."""

def __init__(self, url: str, headers: dict[str, str] = None):
super().__init__()
self.url = url
self.headers = headers or {}

def _create_context(self):
return streamablehttp_client(url=self.url, headers=self.headers)

Both classes take url and headers from the caller and pass them straight to the underlying HTTP client with no allowlisting, no scheme restriction, and no check against private/internal address ranges. headers is forwarded unconditionally, so any caller-attached authorization header goes wherever url points.

Current risk vs. realistic risk

As shipped, this is used by the skill's local eval tooling, where a developer supplies the URL of their own server under test — no attacker-reachable path in that specific usage today.

The composition risk here is more direct than a typical "reusable helper" caveat: SSE/HTTP transports exist specifically to connect to remote MCP servers, and "here is a URL, connect to it" is a natural action for an agent to take in response to content it reads (a document, a tool result, injected instructions) — the same SSRF pattern that has repeatedly affected browsing/fetch-capable agents elsewhere (reaching cloud metadata endpoints, internal admin interfaces, etc.). Any downstream code that lets an agent or untrusted source supply or influence url inherits this with no guardrail, and any code that attaches real credentials via headers risks leaking them to an unintended host.

Classification

CWE-918 (Server-Side Request Forgery), latent/compositional in the shipped code path rather than actively exploitable as-is.

Suggested fix
Enforce an allowlist of permitted hosts, or at minimum require HTTPS and reject private/loopback/link-local ranges (RFC 1918, 127.0.0.0/8, 169.254.0.0/16, ::1).
Require explicit caller confirmation before connecting to a host not already known/trusted.
Do not forward headers (especially authorization headers) to a URL that hasn't been validated against the intended host.
Add a docstring warning on both classes that url must never be derived from untrusted or agent-supplied content without validation.
Reported by

Benedict Kwok, ZTAI Security Advisors LLC ([benedictkwok@ztai.ai](mailto:benedictkwok@ztai.ai)) — found while independently evaluating this skill against NVIDIA SkillSpector.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Direzione di ricerca

Start in mcp-builder/scripts/connections.py at lines 88–109, reading MCPConnectionSSE and MCPConnectionHTTP and their _create_context methods. Trace how caller-supplied url and headers reach sse_client and streamablehttp_client, then define and test the chosen host, scheme, private-range, and header-validation behavior. Done means both transports apply the agreed guardrails and document the untrusted-URL warning.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
networking, security
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
48/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.