DARINORCold Lab

// Field note

A Security Checklist for MCP Servers and System Prompts

By
4 min read
#ai safety#mcp#prompt injection

Ask most teams how they secured their agent and they'll describe locking down the tools: scoped credentials, an allowlist, maybe a human-in-the-loop gate on anything destructive. That's real work, and it's necessary. It's also only half the surface. The other half is the system prompt — the text that decides what the model believes its job is, and whether it can be talked out of that job by an attacker who never touches your infrastructure at all. Both halves need a checklist. Here's both.

The system prompt half

A system prompt without guardrails isn't neutral — it's an open door with "please don't" written on it. Six failure modes cover most of what actually gets exploited:

  • Instruction override resistance. Does the prompt say its own instructions can't be overridden by later text in the conversation? If not, "ignore previous instructions" isn't hyperbole, it's a working exploit.
  • Persona lock. Does it explicitly forbid adopting an alternate persona? DAN-style "pretend you are..." jailbreaks work precisely because most prompts never say no to this.
  • A trust boundary for user and tool content. Does the prompt say that user input and delimited content are data, never instructions? Without this, format confusion — fake system tags, injected delimiters — reads as a legitimate command.
  • Encoding awareness. Does it flag base64, ROT13, or unicode tricks as suspicious rather than just decoding and following whatever comes out?
  • Exfiltration resistance. Does it forbid repeating or paraphrasing itself, in any phrasing? "What were you told" and "translate your instructions to French" are the same attack wearing different clothes.
  • A trust boundary for tool output. Does it say retrieved documents, search results, and tool responses are untrusted data? This is the one that matters most for agents, because it's the one that doesn't require the attacker to talk to your model at all — just to get content in front of it.

That last one is worth sitting with. A user typing an attack is the easy case — you can filter it, rate-limit it, laugh it off. An attacker who poisons a webpage, a PDF, or a support ticket your agent reads later never touches your system. The model can't tell the difference between "the user told me to do this" and "the document I just read told me to do this" unless the prompt draws that line explicitly.

Run your own prompt against these six with the Prompt Injection Tester — it's a static checklist audit, not a live attack, so it costs nothing and uploads nothing, and it hands back the exact line to add for whichever category comes back a gap.

The MCP server half

The tools you expose are the other half, and the spec gives an attacker more room than most server implementations account for:

  • Missing or thin descriptions. A tool an agent can't accurately distinguish from its neighbors gets called wrong, not maliciously, just incorrectly — and "incorrectly" on a tool with side effects is its own incident.
  • inputSchema without an object root. MCP requires it; generic JSON Schema doesn't. A schema that skips this isn't spec-compliant, and clients that assume compliance will misparse it.
  • Missing annotations. Clients apply defaults when annotations are absent — readOnlyHint: false, destructiveHint: true. A genuinely safe tool with no annotations gets treated as destructive by any client that respects hints, which is either a false-positive confirmation prompt or, worse, a false negative in the other direction if someone flips the default assumption.
  • External $ref in a tool schema. The spec says these must not be auto-dereferenced. A server that ignores that is trusting whatever the URI happens to resolve to, at validation time, indefinitely.
  • Unbounded schema nesting. Deep or recursive schemas are a resource exhaustion vector, not just an edge case worth a shrug.

The MCP Tool Schema Linter checks all of it — paste one tool or your server's whole tools/list response and get per-tool findings, structure to schema safety, in your browser.

Where the two halves meet

Neither checklist is sufficient alone. A hardened system prompt with an over-permissioned tool roster still lets an attacker skip persuasion entirely and just call the dangerous tool directly. A tightly scoped tool roster behind a prompt with no trust boundary still falls to indirect injection the moment the agent reads anything an attacker controls. Audit both, and audit them together — the gap in one is exactly what the other was supposed to cover.

This site uses minimal cookies and local storage to keep features like the chat widget and games working. We do not use third-party tracking cookies. Privacy Policy