Large Language ModelsGenerate imagesGenerate videos
OWASP MCP Top 10: Every Risk Explained With Examples
A plain-English walk through all ten risks in the OWASP MCP Top 10, from leaked tokens and tool poisoning to shadow servers and context over-sharing. Each entry has a documented attack, a clear fix, and a one-week plan to apply them in order.
A single MCP server can hand an AI agent your repositories, your inbox, and your database in one afternoon, and approving it often takes one click. That convenience is exactly what the OWASP MCP Top 10 exists to push back on. It names the ten risks most likely to sink a Model Context Protocol deployment, from leaked tokens to servers nobody on the security team knows about. This article goes through every entry in order, shows what the attack looks like with a real or documented example, and closes each section with the fix worth doing first.
The list comes from the OWASP MCP Top 10 project, version 2025, led by Vandana Verma Sehgal. The project page currently lists it in a beta and pilot testing phase, so wording and ordering may still move. Treat the ten entries as a shared vocabulary rather than a finished standard.
What the OWASP MCP Top 10 Is
MCP is the protocol that lets a model call tools. An MCP client (the app hosting the model) connects to one or more MCP servers, and each server exposes tools, resources, and prompts the model can use. Every one of those connections is a trust decision: the server trusts the client to behave, the client trusts the server's descriptions and outputs, and the model trusts whatever text lands in its context window.
The Top 10 maps the places where that trust breaks. Here are all ten at a glance:
ID
Risk
Plain meaning
Cheapest first fix
MCP01
Token Mismanagement and Secret Exposure
Credentials leak through code, logs, or context
Short-lived tokens and secret scanning
MCP02
Privilege Escalation via Scope Creep
Permissions grow past what the task needs
Least privilege with expiry
MCP03
Tool Poisoning
A tool's description or output carries hidden instructions
Pin and hash tool definitions
MCP04
Software Supply Chain Attacks and Dependency Tampering
A malicious or hijacked package becomes your server
Inventory and pin every dependency
MCP05
Command Injection and Execution
Untrusted text reaches a shell
No shell, argument lists, validation
MCP06
Intent Flow Subversion
Retrieved content redirects the agent's goal
Treat retrieved text as data, approve writes
MCP07
Insufficient Authentication and Authorization
Servers do not check who is calling
OAuth 2.1 and per-tool checks
MCP08
Lack of Audit and Telemetry
Nobody can see what the agent did
Log every tool call
MCP09
Shadow MCP Servers
Unapproved servers run outside governance
Inventory and allowlist
MCP10
Context Injection and Over-Sharing
Context leaks across users or tasks
Isolate context per user
💡 Naming note: the project's overview page labels the sixth entry "Prompt Injection via Contextual Payloads", while its detail page for MCP06 is titled "Intent Flow Subversion". Both point to the same slot, and this article uses the detail page title.
Secrets, Permissions and Poisoned Tools
MCP01: Token Mismanagement and Secret Exposure
This is the oldest problem in security wearing a new coat. Hard-coded API secrets, long-lived tokens, and credentials pasted into prompts or config files end up in logs, chat history, and the model's memory. Once a secret sits inside the context window, a prompt injection only has to ask the model to repeat it.
OWASP's scenario: a developer commits a secret during testing, the MCP server reads it at startup, and the assistant later prints it in a reply to someone else.
What to do:
Issue short-lived, narrowly scoped tokens instead of permanent ones.
Run secret scanning on repositories and CI pipelines.
Keep secrets out of tool descriptions, system prompts, and example payloads.
Rotate immediately after any suspected exposure.
💡 Tip: secrets with a fixed prefix are easy to hunt. PicassoIA API secrets start with pia_sk_, so a one-line scanner rule can flag them in any repository. Add the same kind of rule for every provider you use.
MCP02: Privilege Escalation via Scope Creep
Permissions start tight and loosen over time. A token made for one repository gets widened "just for this sprint", an agent gains write access because read access was annoying, and nobody revokes anything. The model ends up holding far more power than any single task needs, so one bad instruction does far more damage.
OWASP's scenario: a prompt injection hidden in a public GitHub issue redirects an agent with broad repository access, and the agent copies private code into a public pull request.
What to do:
Design for least privilege: one scope per task, not one scope per team.
Put an automatic expiry on every grant.
Split read tools from write tools so approvals can differ.
Review agent permissions on a fixed schedule, the same way you review human access.
MCP03: Tool Poisoning
Models pick tools by reading their names and descriptions, which makes those descriptions an attack surface. A poisoned tool hides instructions in its metadata, schema, or output. In April 2025, Invariant Labs demonstrated the attack with an innocent addition tool whose hidden description told the agent to read a local MCP config file and an SSH private file, then pass the contents along in a spare parameter while the reply talked about arithmetic.
A nastier variant is the rug pull: a tool behaves well when you approve it, then changes its description after installation.
What to do:
Pin tool versions and store a hash of each description at approval time.
Alert on any change to a description or schema.
Show users the full tool description, not a shortened summary.
Prefer signed tools from publishers you can name.
MCP04: Supply Chain Attacks and Dependency Tampering
An MCP server is code someone else wrote, pulled from a registry. A compromised or impostor package gets the same access you grant the real one. In September 2025 an npm package called postmark-mcp copied a genuine Postmark integration and added a single line that sent a blind copy of every outgoing email to an address the attacker controlled. Researchers at Koi Security reported it as the first malicious MCP server seen in the wild, and Snyk's write-up walks through the details. It was pulling roughly 1,500 downloads a week before it was removed.
What to do:
Keep an AI bill of materials: every server, its version, and where it came from.
Pin exact versions and read the diff before each upgrade.
Install only from publishers you can verify, and prefer signed releases.
Run dependency scanning before a server is approved, and run unfamiliar ones in a container with no network access until reviewed.
MCP05: Command Injection and Execution
Agents build commands from text. When that text is attacker-controlled (an issue comment, a filename, a web page), the shell does the rest. According to Cycode's breakdown of the list, CVE-2025-6514 in mcp-remote carried a CVSS score of 9.6, affected a package with more than 437,000 downloads, and allowed OS command injection. It sits on the border between this entry and MCP04.
The difference between risky and safe is often one line:
import re
import subprocess
# Risky: untrusted text is spliced into a shell string
subprocess.run(f"git log --author={author}", shell=True)
# Safer: fixed command, argument list, validated input, no shell
if not re.fullmatch(r"[A-Za-z0-9._@][A-Za-z0-9 ._@-]{0,63}", author):
raise ValueError("invalid author")
subprocess.run(["git", "log", "--author", author], shell=False, check=True)
What to do:
Prefer parameterized APIs over shell commands.
When a command is unavoidable, use argument lists and strict input validation.
Apply a deny-by-default policy for which commands a server may run.
Sandbox local servers so a successful injection stays inside a small box.
Hijacked Intent and Open Doors
MCP06: Intent Flow Subversion
The agent reads a web page, an issue, or a PDF, and that content contains instructions. A model cannot reliably tell data from commands, so it may follow them. The result is goal hijacking: the agent still looks like it is doing your task while it serves someone else's.
The clearest real case came from Invariant Labs in May 2025, against the official GitHub MCP server. An attacker opens a malicious issue in a public repository. When the owner asks their agent to look at the open issues, the agent reads the issue, gets injected, pulls data from private repositories into its context, and publishes it in a pull request on the public one. The researchers called it a toxic agent flow, said it was an architectural issue rather than a bug in the server code, and suspected that many people choose an "always allow" approval policy, which removes the human check.
What to do:
Anchor the original goal and check each planned action against it.
Add an independent guardrail model that sees only the user's request and the proposed tool call.
Tag retrieved content as untrusted data and tell the model to treat it as passive text.
Require human approval for anything that writes, sends, or deletes, and never default to "always allow".
💡 Tip: a classifier is one layer, not the whole defense. Llama Guard 4 12B on PicassoIA is a content moderation model that can screen text before it reaches your agent, but it is a safety classifier and not a dedicated injection detector, so keep approvals and least privilege in place.
MCP07: Insufficient Authentication and Authorization
Some MCP servers never ask who is calling. An exposed endpoint with no authentication lets anyone invoke its tools, and a server that checks identity once but never checks permissions per call lets a low-privilege user trigger high-privilege actions.
A concrete case is CVE-2025-49596 in Anthropic's MCP Inspector, rated CVSS 9.4. Versions below 0.14.1 had no authentication between the Inspector client and its proxy, so unauthenticated requests could launch commands over stdio. Chained with a browser flaw and cross-site request forgery, simply visiting a malicious website could run code on a developer machine.
What to do:
Use OAuth 2.1 with multi-factor authentication for people.
Validate the token audience per server, so a token minted for one server fails on another.
Give services managed identities instead of shared accounts.
Bind local servers to localhost and require a token even there.
Check permissions per tool call, not once per session.
Blind Spots and Shadow Servers
MCP08: Lack of Audit and Telemetry
Without logs, every other risk on this list becomes invisible. Token theft, command injection, and prompt injection can all happen with nothing recorded, and incident response turns into guesswork. This entry amplifies the other nine.
A useful tool-call log is small. For each call, record:
Field
Why it matters
Who or what made the call
Ties the action to a user, agent, or service
Which server and tool
Shows which capability was used
Arguments (hashed or redacted)
Lets you replay intent without storing secrets
Result size and status
Exposes bulk reads and silent failures
Timestamp and session ID
Rebuilds the order of events
What to do:
Write logs to immutable storage the agent cannot edit.
Alert on patterns, such as a burst of private reads followed by a write to a public place.
Watch whole sequences of actions, not just single calls.
MCP09: Shadow MCP Servers
A developer spins up an experimental server on a Friday, it keeps running with default credentials and open settings, and by Monday it holds real data. Nobody approved it, nobody monitors it, and it never appears in an inventory. That is a shadow MCP server.
Where to look first:
MCP config files on developer laptops and in shared repositories.
CI/CD pipelines and container registries.
Cloud accounts, for listeners on unusual ports.
Desktop apps and editor extensions that can add their own server entries.
What to do:
Run continuous scanning of those places, not a yearly audit.
Enforce an allowlist so a client refuses unknown servers.
Ban default credentials at the platform level.
MCP10: Context Injection and Over-Sharing
Shared or persistent context windows leak. When one agent serves several users or tenants and the context is not isolated, one person's data can appear in another person's session. The OWASP scenario is a single agent serving many users that leaks one user's personal data into a different session.
It has happened to a real product. BleepingComputer reported that Asana warned users in June 2025 that a logic flaw in its new MCP feature exposed data from some organizations to others. Roughly 1,000 customers were affected, and Asana switched the feature off from June 5 to June 17 while it fixed the bug. It was a logic error, not a hack, and the flaw had been live for about a month before Asana found it.
What to do:
Give every user and tenant its own scoped context window.
Make memory ephemeral by default and expire it fast.
Enforce tenant isolation in the protocol layer, not only in the prompt.
Redact personal data before anything is stored for later reuse.
Which Risks to Fix First
You cannot close all ten in a week, so start where the damage is largest and the work is smallest.
Highest Impact, Lowest Effort
MCP01: turn on secret scanning and shorten token lifetimes.
MCP07: put authentication in front of every server, including the ones on localhost.
MCP09: list every server your team runs today. You cannot protect what you have not counted.
Slower but Necessary
MCP03 and MCP04: pinning and hashing take real setup, but they stop silent changes.
MCP06: approvals and guardrails need design work and constant tuning.
MCP08 and MCP10: logging and isolation touch architecture, so plan them as projects.
MCP02 and MCP05: these sit in between; tighten scopes while you review each server.
A One-Week Hardening Plan
Day
Task
Risks closed
Monday
Inventory every MCP server and client config
MCP09
Tuesday
Scan repos for secrets, rotate anything old, shorten token lifetimes
MCP01
Wednesday
Add authentication and per-tool permission checks
MCP07, MCP02
Thursday
Pin versions, hash tool descriptions, set change alerts
MCP03, MCP04
Friday
Turn on tool-call logging and require approval for writes
MCP08, MCP06
💡 Common mistakes: approving "always allow" to cut clicks, trusting a server because it has many downloads, and logging everything except the tool arguments that matter.
Make Your Own Security Visuals
A security checklist lands harder when people can picture it. Every image in this article uses a plain, physical stand-in for an abstract flaw: a crowded ring of passes for scope creep, a propped-open door for weak authentication, a blank logbook for missing audit trails. You can build the same kind of visuals for your own threat models, training decks, and internal wikis.
Try it on PicassoIA. Open a text-to-image model such as Seedream 5 Pro, Qwen Image 3, or GPT Image 2, describe one real object that stands in for your risk, and add the lighting and lens you want. Generate a few variations, pick the sharpest, and drop it into your next review. If you write the documentation too, the large language models on PicassoIA can help you draft the first version before you edit it by hand.