OWASP MCP Top 10: What a Gateway Fixes — and What It Doesn't
A gateway eliminates some OWASP MCP Top 10 attack paths by construction, puts others behind a switch you still have to throw, and does not reach one category at all. That is the honest short answer, and this post is the long one: each of the ten categories, what a control plane in front of your MCP estate actually does about it, and where the mechanism stops. The reference implementation throughout is ToolMesh, our Apache-2.0 self-hosted MCP gateway, so every claim below is checkable against code you can read.
Three things you will find here that a summary of the list does not give you: the measured exposure figures the list responds to, a category-by-category table with a verdict per row, and a section naming the categories a gateway leaves open — anchored in someone else’s analysis, not our own marketing.
The numbers that made this list urgent
Section titled “The numbers that made this list urgent”The Top 10 did not arrive in a vacuum — and it is older than this summer’s headlines: the list was there before the measurement that made it urgent. In July 2026, Nicolás Padilla published Exposed by Design: A Dynamic Security Assessment of Internet-Facing MCP Servers at Scale (arXiv:2608.00150, v1 submitted 31 July 2026), the first dynamic behavioural assessment of MCP servers reachable from the public internet. Its findings, taken from the paper’s own abstract:
- over 21,000 MCP server instances detectable on the public internet
- 640 production servers confirmed, of which 414 were dynamically audited
- 91.8 % of the dynamically audited servers lack OAuth authentication
- 687 tool instances across the confirmed servers expose shell execution capabilities without access controls
- 41.6 % of confirmed servers disappear within three days between measurement runs
That last number is the one operators should sit with. It describes an estate deployed faster than it can be reviewed. Forkast summarised the wider picture on 11 August 2026, counting more than ten critical or high-severity CVEs in the MCP ecosystem over the same period. One detail worth carrying if you compare write-ups: the 91.8 % applies to the 414 dynamically audited servers, and the 687 shell-capable instances are tools, not servers — several secondary reports round both onto the 640-server figure.
Public-sector guidance landed earlier. On 20 May 2026 the NSA’s Artificial Intelligence Security Center released the Cybersecurity Information Sheet Model Context Protocol (MCP): Security Design Considerations for AI-Driven Automation. Its framing matters more than any single recommendation: alongside serialization risks and trust boundaries, the CSI names dynamic tool invocation, implicit trust relationships, and context sharing as risks that established cyber defence strategies do not adequately address, and argues these cannot be patched at the interface or endpoint level.
That is a structural claim, and it is why a per-server fix does not scale. Twenty-one thousand individually hardened servers is not a plan.
What the OWASP MCP Top 10 actually is
Section titled “What the OWASP MCP Top 10 actually is”Precision about the artefact’s status is part of using it honestly. The OWASP Top 10 for Model Context Protocol is an Incubator project, currently at version v0.1, and its own roadmap places it in Phase 3 — Beta Release and Pilot Testing, with the next release scheduled for October 2026 (project page, checked 18 August 2026). The document is licensed CC BY-NC-SA 4.0.
So: not a certification target, not a compliance baseline, and the IDs still carry the :2025 suffix. What it is is a shared vocabulary for MCP risk, which is exactly what the category was missing. Treat it as a checklist for design review rather than an audit standard — and expect the categories to move in October.
The ten categories, as given in the summary list on the project page:
| ID | Category |
|---|---|
| MCP01:2025 | Token Mismanagement & Secret Exposure |
| MCP02:2025 | Privilege Escalation via Scope Creep |
| MCP03:2025 | Tool Poisoning |
| MCP04:2025 | Software Supply Chain Attacks & Dependency Tampering |
| MCP05:2025 | Command Injection & Execution |
| MCP06:2025 | Intent Flow Subversion |
| MCP07:2025 | Insufficient Authentication & Authorization |
| MCP08:2025 | Lack of Audit and Telemetry |
| MCP09:2025 | Shadow MCP Servers |
| MCP10:2025 | Context Injection & Over-Sharing |
One caveat about that table, and it is the sharpest available evidence for the beta status above: the project page does not agree with itself. The summary list gives MCP06 as Intent Flow Subversion. A second, fuller listing further down the same page titles the same entry Prompt Injection via Contextual Payloads — and in that listing the IDs lose their zero padding (MCP1:2025, MCP4:2025, MCP5:2025, MCP6:2025, MCP8:2025) while MCP03 and MCP07 keep theirs. Both readings were live on the page on 18 August 2026. We use the summary list throughout this post. If you cite OWASP MCP06 anywhere else, say which of the two titles you mean, because they describe noticeably different things: one is about hijacked intent, the other about prompt injection as an injection class.
The mapping at a glance
Section titled “The mapping at a glance”ToolMesh runs every tool call through one pipeline. The source comment states the order plainly: AuthZ → Credentials → Gate pre → Backend → Gate post → Audit (internal/executor/executor.go). The mapping below is that pipeline held against the ten categories, with a verdict per row.
| OWASP category | Mechanism | Verdict |
|---|---|---|
| MCP01 Token Mismanagement & Secret Exposure | Credentials injected server-side per request; never in client config or model context | Client/model exposure closed; credential lifecycle open |
| MCP02 Privilege Escalation via Scope Creep | OpenFGA relationship check per call; discovery filtered by the same check | Enforced when configured |
| MCP03 Tool Poisoning | REST tool definitions come from operator-held YAML, not from the upstream server | Closed for DADL backends, open for aggregated MCP servers |
| MCP04 Supply Chain Attacks & Dependency Tampering | A backend is ~30 lines of YAML, not a package; strict parser rejects unknown fields | Reduced, not eliminated |
| MCP05 Command Injection & Execution | Tools are declared HTTP calls with typed parameters; no shell unless you add one | Shell injection closed at the tool layer; backend injection remains |
| MCP06 Intent Flow Subversion | Blast-radius limits only: authorization ceiling, output policies, audit trail | Not closed |
| MCP07 Insufficient Authentication & Authorization | OAuth 2.1 issuer, PKCE mandatory, S256 only; bcrypt API keys | Authentication closed; authorization only when enforcement is on |
| MCP08 Lack of Audit and Telemetry | Structured audit entry on every exit path, denials included | Recorded everywhere; not immutable, and the write itself is fail-open |
| MCP09 Shadow MCP Servers | One endpoint, one file-declared catalog — an inventory by construction | Consolidated, not prevented |
| MCP10 Context Injection & Over-Sharing | goja policy engine pre and post execution; Code Mode projects results | Enforced when configured |
The ten categories, one by one
Section titled “The ten categories, one by one”MCP01:2025 — Token Mismanagement & Secret Exposure
Section titled “MCP01:2025 — Token Mismanagement & Secret Exposure”The failure mode is a backend API key sitting in a client config file, or worse, passing through the model’s context on its way to a tool. In ToolMesh, backend credentials never reach the client. They resolve inside ExecuteTool() at step 2 of the pipeline and are attached to the outbound request by the adapter — the agent asks for netbox_list_devices, not for a token. Revoking a key touches the gateway, not thirty client configurations.
Honest scope, and it is wider than it first looks. The shipped credential store is the embedded one, reading CREDENTIAL_* environment variables; Vault, OpenBao and Infisical adapters are documented as the tiering path, but the open-source binary today ships the embedded store, and per-user credential resolution is an accepted-design ADR rather than running code. More importantly, OWASP’s own scope for MCP01 goes past exposure: its description names long-lived tokens explicitly and calls short-lived, scoped credentials essential. The OWASP MCP Security Cheat Sheet is blunter still — do not store secrets in server code, configs, or environment variables, and prefer ephemeral tokens to long-lived ones. Read against that, ToolMesh closes the path from credential to model and leaves credential lifecycle where it found it.
MCP02:2025 — Privilege Escalation via Scope Creep
Section titled “MCP02:2025 — Privilege Escalation via Scope Creep”Authorization runs first in the pipeline, per call and per user, against an OpenFGA relationship model in a User → Plan → Tool structure. The detail worth knowing: the same check filters tool discovery, so a user who may not call a tool does not see it in the listing either. Scope-to-filter injection goes one step further and narrows backend query parameters from the caller’s scope, so authorization shapes the request rather than only permitting it.
Honest scope: ToolMesh ships with OPENFGA_MODE=bypass as the default — no authorization checks at all. Enforcement is one setting (restrict) plus a relationship model you have to write, and a gateway configured for convenience enforces nothing. The model is documented under Authorization.
MCP03:2025 — Tool Poisoning
Section titled “MCP03:2025 — Tool Poisoning”The rug-pull variant of this attack works because an MCP client re-reads tool definitions from the server, so a description approved in review can change afterwards. For backends declared in DADL, that channel does not exist: RESTAdapter.ListTools reads the parsed YAML file the operator holds — it takes no context and makes no upstream call. The catalog changes when someone edits a file in your repository, which is a reviewable event with an author attached.
Honest scope: this holds for DADL-declared REST backends. Where ToolMesh aggregates a genuine upstream MCP server, MCPAdapter.ListTools does query that server, and those definitions are exactly as trustworthy as their source. In neither case does the gateway semantically inspect a description for hidden instructions — pinning is not detection.
MCP04:2025 — Software Supply Chain Attacks & Dependency Tampering
Section titled “MCP04:2025 — Software Supply Chain Attacks & Dependency Tampering”Every MCP server you add is normally a package, a runtime, and a transitive dependency tree. That cost model is the starting point of our own preprint, DADL: A Declarative Description Language for Enterprise Tool Libraries in LLM Agent Systems (arXiv:2605.05247, 4 May 2026): at organizational scale every API integration ships as a dedicated server process with its own deployment, dependency tree and credential handling — while the overwhelming majority of those servers turn out to be thin wrappers around REST APIs. With DADL, adding an API means adding a YAML file: no third-party code enters the runtime. The parser is explicit about what it does not understand, which is a weaker and more useful property than strictness: an unknown key is re-decoded strictly, reported as a warning and then ignored — the DADL spec’s warn-and-ignore rule, so a file using newer additive features still loads, visibly degraded rather than silently. Two things do fail closed: a requires block naming a capability this build lacks refuses the load outright, and a behaviour-determining value this version does not implement — a pagination behaviour, a stream handling — is rejected rather than guessed.
Honest scope: this shifts the supply chain rather than removing it. The gateway binary has its own Go dependency tree, and a malicious DADL file is still a config-supply-chain problem — the mitigation is that it is reviewable YAML in git rather than minified code in node_modules.
MCP05:2025 — Command Injection & Execution
Section titled “MCP05:2025 — Command Injection & Execution”Set against the paper’s 687 tool instances with unrestricted shell execution, this is the most structural difference in the list. A DADL tool is a declared HTTP call: method, path, and a typed parameter schema. There is no shell to inject into, because there is no shell — one appears only if an operator deliberately adds a backend that exposes one. Outbound URL validation fails closed on DNS resolution errors and treats unresolvable addresses as private, which is the SSRF-to-cloud-metadata path the same paper reports finding in the wild.
Honest scope: OWASP’s category is broader than shells. Its description covers an agent constructing and executing system commands, shell scripts, API calls, or code snippets from untrusted input without validation — and constructing API calls is exactly what DADL does for a living. A typed string parameter stops the tool layer from becoming an interpreter; it does not stop the backend on the far end from passing that string into its own SQL or shell. If the backend API itself exposes a command-execution endpoint, DADL will expose it faithfully. Declarative binding constrains the transport, not the API you point it at, and input validation against the backend’s semantics remains yours to write — in the gate, if nowhere else. The MCP03 split carries over unchanged, too: aggregate an upstream MCP server that ships a shell tool, and the gateway passes that tool through — subject to authorization and the gates like any other tool, but “no shell” is a property of the DADL layer, not a filter imposed on foreign catalogs.
MCP06:2025 — Intent Flow Subversion
Section titled “MCP06:2025 — Intent Flow Subversion”This is the category a gateway does not close, and pretending otherwise would discredit the other nine. When injected context steers an agent toward an attacker’s goal, the resulting tool call is authenticated, authorized, schema-valid, and wrong. Every check in the pipeline passes, because every check answers whether this caller may do this thing — not why they are asking.
What the pipeline does contribute is a ceiling and a record: authorization bounds what a subverted agent can reach at all, output policies can block specific exfiltration shapes, and the audit log makes the trajectory reconstructable afterwards. Semantic authorization — an LLM supervisor reasoning about intent — exists in our concept notes and not in the binary. Until it does, treat MCP06 as unmitigated and design the blast radius accordingly.
MCP07:2025 — Insufficient Authentication & Authorization
Section titled “MCP07:2025 — Insufficient Authentication & Authorization”Against the 91.8 % figure, the authentication half of this category has a sharp answer. ToolMesh acts as an OAuth 2.1 issuer: PKCE is mandatory, S256 is the only accepted challenge method, and a request without code_challenge is rejected at the authorization endpoint. API keys and user passwords are bcrypt-hashed. No anonymous caller reaches a tool.
Honest scope: the category is called Authentication & Authorization, and the second word lands where MCP02 already left it — OPENFGA_MODE defaults to bypass, so out of the box every authenticated caller is also a fully authorized one. Saying the pipeline’s authorization step “passes” in that mode would be a word game: no authorization decision is taken at all. Strictly read, ToolMesh closes the authentication half of MCP07 by construction and hands you the authorization half as a configuration task. Beyond that, TLS terminates in front of the gateway (Caddy, nginx, or Cloudflare Tunnel), identity is local — users.yaml and apikeys.yaml, or the built-in issuer — and OIDC connectors to Keycloak, Entra, Okta or Zitadel are roadmap, not shipped. The current surface is documented under Authentication.
MCP08:2025 — Lack of Audit and Telemetry
Section titled “MCP08:2025 — Lack of Audit and Telemetry”An audit entry is written on every exit path of the pipeline, including the ones that never reach a backend: authorization error, authorization denial, pre-gate rejection, backend error, post-gate rejection, and success. Denials are the entries that matter during an incident, and they are the ones homegrown logging most often misses. Storage is structured slog to stdout or SQLite (AUDIT_STORE), with retention configurable and defaulting to 90 days; Prometheus metrics run alongside.
Honest scope, in two parts. First, the log is trustworthy exactly as far as the host is: tamper-evidence — hash chaining with external anchoring — is an ADR draft, not an implementation, and OWASP asks for immutable audit trails while the Cheat Sheet adds SIEM ingestion and alerting on top. Neither is in the box. Second, and less obvious: the audit write is deliberately fail-open. The source comment says so in as many words — audit recording failures do not block the tool response, because availability is prioritized over auditability. So the pipeline is fail-closed at the steps that decide whether a call happens, and fail-open at the step that records it. If your requirement is that no unlogged call may ever execute, ToolMesh does not meet it today; you would run an external audit pipeline and alert on the error entries.
MCP09:2025 — Shadow MCP Servers
Section titled “MCP09:2025 — Shadow MCP Servers”Consolidation is the whole answer here, and it is a deployment property rather than a clever feature. One endpoint, one catalog, declared in files: our own production instance currently fronts 5,590 tools across 60 backends behind a single MCP endpoint (checked 18 August 2026). Asking “what can our agents reach?” is reading a directory, not running a network scan.
Honest scope: a gateway does not stop anyone from running an MCP server beside it. Preventing shadow deployments is egress policy, asset management and organisational discipline. What a gateway removes is the reason to spin one up — and it gives you something to compare a scan against.
MCP10:2025 — Context Injection & Over-Sharing
Section titled “MCP10:2025 — Context Injection & Over-Sharing”The Output Gate is a goja JavaScript policy engine that runs twice per call: pre-execution on the request, post-execution on the response, with a five-second timeout per policy. Shipped policies cover PII redaction, role-based field filtering and caller blocking; redaction itself fails closed. Code Mode attacks the same category from the other side — the agent runs typed JavaScript against the tools and returns only what it projects, so a thousand-row response can be reduced to five fields before anything enters the context window.
Honest scope: the open-source gate is deterministic rules only. The LLM-based compliance evaluator is an enterprise extension, and human-in-the-loop review is not implemented at all. A rule catches what you wrote it to catch.
What a gateway does not solve
Section titled “What a gateway does not solve”The most useful critique of the gateway pattern this year came from outside the vendor field. In Securing MCP in Production: Defense-in-Depth beyond the Gateway (InfoQ, 29 July 2026), Nik Kale grants that gateways deliver central authentication, authorization, auditing and policy evaluation — and then structures what still has to exist around them into four defense layers, each of which, he argues, has its earliest trustworthy enforcement point somewhere other than the gateway. His verdict on the pattern is two three-word sentences: “It is necessary. It is insufficient.” We agree, and held against the map above his four layers split evenly: two land where DADL already changes the mechanics, two sit beyond anything a pipeline reaches.
- Safe tool execution. A gateway cannot ensure that a tool handler treats its arguments as data rather than instructions. For DADL-declared backends this layer collapses by construction: there is no handler code to get wrong, because the gateway itself builds the HTTP call from the typed schema. The MCP05 limits stay standing — what the backend does with the values, and every handler inside an aggregated MCP server, sit beyond it.
- The management plane. The inspectors, harnesses, dashboards and consoles around MCP are not behind the gateway, and they frequently hold more privilege than the agents do. Nothing in the pipeline above protects them.
- Outbound trust, egress and token scope. Server-side injection stops a credential from reaching the model. It does not stop a backend from being handed a token broader than the task needed, or from making its own unsafe outbound calls with it. Credential scoping is a decision you make when you write the DADL, and no pipeline stage rescues an over-broad token.
- Semantic integrity and manifest pinning. Kale’s fourth layer is the rug-pull problem from MCP03, and he points out that the MCP specification is silent on pinning — functionality teams have to build at the gateway themselves. DADL-declared backends get it by construction; aggregated MCP servers do not. That is exactly where our MCP03 verdict splits.
One category from the table appears in none of the four layers: MCP06. A call that is authenticated, authorized and schema-valid, made for an attacker’s reasons, is not an execution problem, a management-plane problem, an egress problem or a manifest problem. Which is one more way of saying what the verdict column already does: a gateway does not close it, with or without the layers around it.
We add one gap of our own, because it applies to us specifically: a gateway concentrates risk as much as it concentrates control. Consolidating 60 backends behind one endpoint means that endpoint holds every credential and fronts every tool — an internet-facing MCP endpoint and a high-value target in one object. It needs its own hardening, its own exposure review, and a place in the estate you audit rather than only being the tool you audit with. We track that as an open item on our own instance, not as a solved problem.
Two things are worth saying against the temptation to read all of this as an argument for doing nothing. First, the pattern is not speculative: in A Gateway Architecture for Enterprise MCP Authentication (arXiv:2608.10760, v1, 11 August 2026), a team of authors with PayPal affiliations describes exactly this consolidation — per-team authentication implemented independently, no consistent way to authorize callers or offboard a departing employee — and reports an architecture in production fronting dozens of internal MCP servers. The paper itself does not name the operator; the affiliation is visible in the authors’ addresses. Independent of any vendor, the category is being validated at enterprise scale. Second, “insufficient” is not “useless” — and OWASP says as much from its own side. The MCP Security Cheat Sheet recommends using an MCP proxy or gateway to enforce isolation policies between servers, and pinning tool definitions to detect rug pulls. Those are two of the mechanisms described above, recommended by the same foundation that publishes the risk list. Every category except MCP06 gets materially better at the gateway — and gets better once, rather than separately on every server.
Where ToolMesh stands
Section titled “Where ToolMesh stands”ToolMesh is an Apache-2.0, self-hosted MCP gateway written in Go that runs every tool call through one central enforcement pipeline — authorize, inject credentials, gate, execute, gate, audit — fail-closed at each enforcement step you have switched on, and, as noted under MCP08, fail-open at the audit write. Backends are declared in DADL, YAML files you keep in git, which is why the tool catalog is a reviewable artefact rather than a runtime negotiation. The architecture behind the pipeline is laid out in Anatomy of an Enterprise Tool Library; what the pattern looks like under the new stateless spec is in MCP Goes Stateless.
Where we come out on the Top 10, read strictly: not one category is fully closed in OWASP’s own scope. What a gateway does is narrower and more useful than a row of green ticks. It eliminates specific attack paths by construction — credentials reaching the model, an interpreter at the tool layer, rug-pulled tool definitions on DADL-declared backends. It puts several more behind one switch that has to be thrown, and bypass is the default. It improves the rest by consolidation rather than by mechanism. And MCP06 sits outside its boundary entirely. That is a defensible position for August 2026 and not a finished one. The OWASP list moves to its next release in October, and we would rather re-run this mapping against the new version than quietly let it age.
If you run the same mapping against your own estate and reach a different verdict on any row, GitHub Discussions is open — a disagreement about one of these ten is more useful to us than agreement about all of them.
Sources
Section titled “Sources”| Source | Date | Used for |
|---|---|---|
| OWASP Top 10 for MCP | v0.1, checked 18 Aug 2026 | Category IDs, titles and scope; project status; the MCP06 discrepancy |
| OWASP MCP Security Cheat Sheet | undated, checked 18 Aug 2026 | Credential guidance, tool pinning, gateway isolation, SIEM |
| arXiv:2608.00150 — Exposed by Design | v1, 31 Jul 2026 | 21,000+ instances, 640/414 servers, 91.8 %, 687 tools, 41.6 % |
| NSA AISC Cybersecurity Information Sheet on MCP | 20 May 2026 | Dynamic tool invocation, implicit trust, context sharing |
| Forkast — MCP security inflection point | 11 Aug 2026 | 10+ critical/high CVEs, ecosystem context (secondary source) |
| InfoQ — Defense-in-Depth beyond the Gateway | 29 Jul 2026 | The four defense layers beyond the gateway |
| arXiv:2608.10760 — A Gateway Architecture for Enterprise MCP Authentication | v1, 11 Aug 2026 | Independent production validation of the pattern |