The difference between a secure AI integration and a CVSS 9.8 was a single middleware. In early March 2026, researchers at Pluto Security found that nginx-ui — the popular open-source web dashboard for managing nginx — had shipped MCP (Model Context Protocol) support with two HTTP endpoints: /mcp, guarded by both IP whitelisting and authentication, and /mcp_message, guarded by IP whitelisting alone. And the default IP whitelist was empty, which the middleware treated as "allow all."
One missing AuthRequired() check. That was the entire vulnerability: any host on the network could POST to /mcp_message and invoke all 12 MCP tools with no credentials — reading nginx configs, writing new ones, and triggering the automatic reload that applied them instantly. Tracked as CVE-2026-33032 with a CVSS score of 9.8, fixed in nginx-ui 2.3.4, and under active exploitation within weeks across roughly 2,600 internet-exposed instances. Pluto Security codenamed it MCPwn.
This post is the mechanism, the pattern it belongs to, and the part that lands on you: a pre-ship review checklist for any self-hosted panel — Coolify, Dokploy, or your own PaaS console — that is about to bolt agent access onto a dashboard that already has something worth protecting.
What 12 unauthenticated tools actually buy an attacker
nginx-ui added its MCP server in late 2025 so AI clients could manage nginx configs in natural language. The tool set mirrors the dashboard's own capabilities: full CRUD over config files plus lifecycle operations.
Behind authentication, that is a convenience feature. Without it, every tool is a remotely callable primitive. Here is what the exposed surface amounted to:
| Tool class | Example tools | What an unauthenticated caller does with it |
|---|---|---|
| Config reads | nginx_config_get, nginx_config_list, nginx_config_base_path, nginx_config_history | Steal TLS private keys and upstream credentials out of configs, map the proxy topology, learn exactly when reloads happen |
| Config writes | nginx_config_add, nginx_config_modify | Plant a malicious server block: traffic interception, a backdoor proxy_pass, malicious redirects |
| Reload | reload_nginx | Apply the planted config instantly — no second step, no waiting for an operator |
| Site lifecycle | nginx_config_enable, nginx_config_disable, nginx_config_rename, nginx_config_mkdir | Disable legitimate sites for disruption or extortion, stage payload files on disk |
The end-to-end attack path is three steps: reach /mcp_message (the empty default whitelist waves you through, no credentials asked), invoke a config-write tool to drop a malicious server block, and let the automatic reload take it live. As Pluto Security put it, one unauthenticated API call is all it takes to inject a config and take over nginx — enabling traffic interception, backdoors, disruption, and theft of sensitive information. There is no privilege escalation here because there was no privilege boundary to escalate past: the tools inherited the dashboard's full capability while skipping its authentication entirely.
The timeline shows how fast "missing auth on a new endpoint" becomes "emergency." Pluto Security reported the flaw to the maintainers in early March 2026; version 2.3.4 shipped the fix on March 15; by mid-April the flaw was confirmed under active exploitation in the wild, with VulnCheck adding it to its Known Exploited Vulnerabilities list and Recorded Future flagging it as one of 31 high-impact vulnerabilities exploited during March 2026 with a risk score of 94 out of 100. Pluto's Shodan scans found more than 2,600 publicly exposed instances in the window between disclosure and patching.
The pattern: MCPwn was the second disclosure, not the first
MCPwn deserves attention beyond one dashboard's bad month because Pluto Security says it is a pattern, not an accident. It was, in the words of Yotam Perkal, Pluto's director of security research, "the second critical MCP vulnerability we've disclosed this year, with many more in coordinated disclosure." The consistent shape: "AI integration endpoints expose the same capabilities as the core application but often skip its security controls."
The first disclosure was MCPwnfluence: two flaws in mcp-atlassian — one of the most popular MCP servers in the ecosystem at 4,400-plus stars and 4 million-plus downloads — that chained into unauthenticated remote code execution from the local network. CVE-2026-27825 (CVSS 9.1) allowed arbitrary file writes through path traversal in attachment downloads; CVE-2026-27826 (CVSS 8.2) added SSRF via unvalidated URL headers, letting the MCP server act as a proxy into internal networks. Chain them and an attacker sends requests to the MCP server from the LAN, redirects it to an attacker machine, uploads an attachment, and gets full unauthenticated RCE.
Why does the same failure keep recurring? Because of where agent interfaces get built. The core application's auth lives in its HTTP middleware and session handling — mature, reviewed, tested. The MCP integration arrives later as a second transport into the same service layer, often registered as new routes beside the UI's, sometimes under the folk assumption that it is "agent-only" or "internal."
Capabilities are inherited for free through the shared backend; controls are not, because controls were attached to the old transport, not the capability. A developer who would never ship an unauthenticated "overwrite nginx.conf" button in the dashboard ships exactly that as a tool definition, because the tool definition looks like a schema, not an endpoint. MCPwn is what that category error costs: twelve endpoints' worth of admin API with the auth of a health check.
Your panel is shipping the same surface right now
The reason this matters past nginx-ui is that every self-hosted panel is currently adding the same interface. Coolify v4.0, launched in May 2026, ships a built-in MCP server that lets any MCP-aware AI client — Claude Code, Cursor, Cline — issue deployment commands in natural language. Dokploy goes further: its official MCP package exposes the entire Dokploy API as MCP tools, 508 tools across 49 categories, from project and application management to databases, Docker, backups, SSO, and notifications. Community projects fill the gaps, like the MCP server for Nginx Proxy Manager that automates proxy hosts, Let's Encrypt certificates, and access lists from any MCP client.
Do the arithmetic. nginx-ui fell with 12 tools, of which exactly one write-plus-reload pair was enough for full takeover. Dokploy's MCP surface exposes 508 tools — the complete API, every destructive operation included — as remotely callable primitives.
None of this is an accusation against those projects; it is a statement about blast radius. Every tool a panel exposes to agents is an endpoint that needs the same authentication, authorization, and audit story as the dashboard button that calls the same backend function. The panels shipping hundreds of tools at once are multiplying the exact review surface where nginx-ui missed a single middleware.
If you maintain a panel, a PaaS console, or any dashboard with "agent access" on the roadmap, the question is not whether to ship it — agentic operation is genuinely the direction of travel — but whether the agent transport gets the security review a second admin API deserves, or the rubber stamp a "developer convenience" usually gets.
The pre-ship checklist for any panel adding agent access
Seven items, each one a control that would have stopped MCPwn or contained it. Run them before the MCP endpoint is reachable, not after the disclosure.
- Authenticate every MCP transport — not just the "main" one. The MCP authorization specification has mandated OAuth 2.1 for remote servers, with the MCP server acting as an OAuth resource server validating audience-bound tokens. Enumerate every transport you ship — SSE endpoints, streamable HTTP, any stdio bridge that touches a socket — and require auth on each. nginx-ui's failure was literally one sibling route missing the middleware the other had.
- Fail closed on empty policy. An empty IP whitelist, an unconfigured allowlist, a missing auth server URL — every one of these must mean deny-all, never allow-all. Defaults ship to production; the default posture must be the safe one. This single invariant would have neutered MCPwn even with the missing middleware.
- Scope tools to least privilege with a read/write split. Separate read tools from write tools and let operators enable them independently. An agent doing deploy-status checks needs
config_get, notconfig_modifyplus reload. Short-lived, narrowly scoped tokens beat one bearer token that can do everything the dashboard can. - Bind the MCP listener separately from the public UI. Localhost-only by default, its own port and listener, deliberate opt-in to expose it further. A network-reachable agent port sitting next to the public dashboard is exactly the MCPwn topology: convenient, and one mistake from unauthenticated admin.
- Audit-log every tool invocation. Which identity called which tool, with which arguments, and what changed as a result. nginx-ui operators had to reconstruct intrusions from nginx logs alone; a tool-invocation trail is the difference between "we were exposed" and "here is everything the attacker touched."
- Ship a one-switch kill-switch. A single flag that disables the entire MCP surface without touching the dashboard. Pluto Security's own fallback advice for operators who could not patch immediately was to disable MCP functionality entirely — make that a config line, not a redeploy.
- Verify with an unauthenticated repro before release.
curlevery MCP endpoint with no credentials in CI and assert 401 or 403. If your test suite never hits the agent port without a token, the first party to try it is an attacker with Shodan.
If you run nginx-ui, do this today
Upgrade to version 2.3.4 or later immediately — every version at or below 2.3.3 is affected. Then review your nginx logs and config history for unexpected configuration changes, since exploitation leaves no trace in the dashboard itself. If you cannot patch yet, disable the MCP functionality entirely until you can. Treat any unpatched, network-reachable instance as potentially compromised and rotate any credentials that lived in its configs, including TLS keys.
Conclusion: MCP is the new admin API
Step back and MCPwn reads less like a bug and more like a preview. Every dashboard that adds "agent access" is adding a second admin API — one consumed by software that acts faster, retries more persistently, and explores more combinatorially than any human clicking through a UI. nginx-ui's 12 tools, mcp-atlassian's file-write chain, and Pluto Security's warning of more MCP disclosures already in coordinated disclosure all point the same way: the agent transport is now the highest-leverage attack surface on the panels it touches, and it is being reviewed like a side feature.
The fix is cultural more than technical. The MCP spec already mandates OAuth 2.1, audience-bound tokens, and protected-resource metadata; the primitives exist. What is missing is the reflex to treat a tool definition with the suspicion of a new route handler.
Auth on every transport, fail-closed defaults, least-privilege scopes, separate listeners, audit trails, kill-switches, and an unauthenticated repro in CI. Panels exposing hundreds of tools need that discipline hundreds of times over, which is exactly why the checklist has to be mechanical rather than heroic. Ship the agent interface. Just ship it like the admin API it is.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with AI agents as first-class operators. Star the repo on GitHub or deploy your first app today.



