Analysis

How Do You Stop Prompt Injection in an MCP Server? | Data Science Collective

Page published · Page updated

Dossier

Coverage timeline

26 May 2025dev.to 31 Jul 2026dzone.comobserved 29 Aug 2026medium.comcolrows.com

Why it matters

MCP-connected agents combine trusted tools with untrusted inputs, so defenders need architectural controls—not prompting—to prevent prompt injection from turning ordinary agent tasks into data-exfiltration channels.

An explainer on preventing prompt injection in Model Context Protocol (MCP) servers, framing the risk around Simon Willison's "lethal trifecta" (private data access, exposure to untrusted content, and external communication). The article recaps the May 2025 Invariant Labs demonstration against the official GitHub MCP server, where a malicious GitHub issue hijacked a coding agent into leaking private repository data into a public pull request, and argues the fix must be architectural rather than prompt-based.

guidance

Summary

This article is defensive guidance for builders of Model Context Protocol (MCP) agents, arguing that indirect prompt injection is an architectural problem that cannot be solved with prompting alone. It frames the risk through Simon Willison's 'lethal trifecta' — an agent that simultaneously has access to private data, exposure to untrusted content, and the ability to communicate externally — and shows how MCP makes assembling that trifecta trivially easy by config.[0][11]

The central case study is the May 2025 Invariant Labs demonstration against the official GitHub MCP server, where a booby-trapped GitHub issue instructed a coding agent to read the user's private repositories and publish personal details into a public pull request. No tool was compromised and no CVE was filed; the exploit lived entirely in data the agent treated as instructions.[0]

The recommended defense is a deterministic broker that sits outside the model's reasoning loop and enforces least-authority credentials, taint tracking of untrusted content, egress allowlisting, human approval on tainted egress, and schema pinning — so that no single session ever wields all three trifecta legs with real authority. The author notes the MCP 2025-06-18 spec closes protocol-level holes (audience-bound tokens via RFC 8707, no token passthrough) but cannot fix indirect prompt injection, which remains the builder's architectural responsibility.[0]

How it works

Indirect prompt injection works because to an LLM every token in the context window is potentially an instruction. Text returned by a tool (a GitHub issue, web page, ticket, or PDF) is assumed to be data, but the model has no privileged channel separating operator instructions from ingested content, so attacker-authored text competes directly with — and often beats — a guardrail system prompt because it is more specific and more recent.[0][11]

The GitHub MCP heist chained the three trifecta legs: an attacker-filed issue (untrusted content) instructed the agent to enumerate private repositories (private-data access) and write the collected details into a pull request on the public repo (external communication/exfiltration). Because each MCP tool acted as documented, no server-side vulnerability was involved.[0]

A control that lives inside the reasoning loop can be argued with, whereas a control in deterministic code outside the loop cannot be addressed by an injection. The proposed broker inspects each tool call: if an egress-capable tool (e.g. create_pr, send_email, http_fetch) is invoked from a session already tainted by untrusted content, the trifecta is complete and the broker refuses to let the model self-authorize, requiring human approval.[0]

Affected versions and patch status

ProductAffectedPatch status
Official GitHub MCP server (via MCP-wired coding agents)Susceptible to indirect prompt injection via attacker-authored GitHub issues; demonstrated May 2025Not a code vulnerability — no CVE or patch; mitigation is architectural (broker outside the reasoning loop)[0]
MCP Inspector (debug surface)Exposed unauthenticated MCP Inspector — CVE-2025-49596, CVSS 9.4 remote code executionArticle advises treating unauthenticated debug surfaces as radioactive and patching them[0]
Model Context Protocol authorization specRevisions prior to 2025-06-18 lacked mandatory audience binding / no-passthrough rules2025-06-18 revision makes servers OAuth Resource Servers and mandates RFC 8707 Resource Indicators and no token passthrough[0]

Key takeaways

  • The trifecta, not any individual tool, is the threat: a fleet of perfectly trustworthy MCP servers still combines into a breach when one session holds private data, untrusted input, and an egress path at once.[0]
  • Assume prompt injection succeeds — you cannot reliably stop attacker text from reaching the model, so design to dismantle the weapon (deny the combination of capabilities) rather than prevent every trigger.[0][11]
  • Guardrails must live outside the reasoning loop; break at least one trifecta leg per session by scoping every credential to one audience, tainting untrusted content, and gating every egress-capable tool.[0]
  • The MCP spec fixes token- and schema-level attacks but cannot fix indirect prompt injection, which is a consequence of pointing a capable agent at attacker-controlled text while it holds your keys — that remains the builder's architectural responsibility.[0]

Defensive actions

  • Place a deterministic broker between the agent and its MCP servers that enforces policy in ordinary code outside the model's reasoning loop.: A prompt asking the model to be careful is a control the attacker can address directly; a broker in deterministic code cannot be sweet-talked, so consequential egress decisions are taken away from the model.[0]
  • Grant each tool a least-authority, short-lived credential scoped to exactly one audience, using RFC 8707 resource indicators, and never mint or forward god-tokens.: A token good only for pr:write on one server cannot be replayed to read a database, defusing the private-data leg, the confused-deputy problem, and token passthrough; short TTLs limit stolen-token replay.[0]
  • Taint-track all untrusted tool results and gate every egress-capable tool behind an allowlist, requiring human approval when the session is tainted.: Marking untrusted content makes the injection leg visible and prevents a tainted session from self-authorizing data movement to a non-allowlisted host, breaking the full trifecta as in the GitHub-issue heist.[0]
  • Pin approved tool schemas by hash and halt for re-approval if a live schema changes.: Tool poisoning and rug pulls live in the tool descriptions the model reads; a silent schema mutation becomes a loud, reviewable event.[0]
  • Adopt the MCP 2025-06-18 authorization spec (audience-bound tokens, no passthrough), the security best-practices guidance, and patch exposed debug surfaces such as MCP Inspector.: The spec closes protocol-level holes around tokens and schemas; unpatched debug surfaces like the one behind CVE-2025-49596 can yield unauthenticated RCE at CVSS 9.4.[0]