MCPwn (CVE-2026-33032): nginx-ui MCP endpoint hands over the web server
An unauthenticated MCP endpoint in nginx-ui ≤ 2.3.3 lets any network attacker rewrite nginx configs and restart the service. CVSS 9.8, publicly disclosed on April 15, 2026, exploited in the wild within hours of the patch.
What is this?
CVE-2026-33032, codenamed MCPwn by Pluto Security, is a critical authentication bypass in nginx-ui, the popular open-source web interface for managing nginx servers. The flaw sits inside the project’s newly added Model Context Protocol (MCP) integration: one of the two MCP HTTP endpoints was registered without the authentication middleware that protects every other administrative route.
The vulnerability was identified by Pluto Security on March 4, 2026, reported to maintainers on March 14, and patched the next day in version 2.3.4 (March 15, 2026). Pluto published the technical write-up on April 15, 2026, the CVE was added to the VulnCheck Known Exploited Vulnerabilities (KEV) catalog on April 13, 2026, and several vendors — Recorded Future, BleepingComputer, eSentire — confirmed active exploitation in the wild starting in late March, before most operators had deployed the fix. The CVSS score is 9.8 (Critical).
How it works
When nginx-ui added MCP support to expose its admin actions to LLM agents, two HTTP endpoints were declared on the router:
POST /mcp— protected by IP whitelisting and theAuthRequired()middlewarePOST /mcp_message— protected by IP whitelisting only
The two endpoints accept the same MCP tool-call payloads. The second one was simply missing one line in the route registration:
// Conceptual sketch of the vulnerable route registration,
// based on the public April 15, 2026 disclosure and the
// patch commit 413dc63. No payload against any live system
// is reproduced here.
// Vulnerable (nginx-ui ≤ 2.3.3)
r.POST("/mcp", middleware.IPWhiteList(), middleware.AuthRequired(), mcp.Handle)
r.POST("/mcp_message", middleware.IPWhiteList(), mcp.Handle)
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// AuthRequired() missing here
// Patched (nginx-ui ≥ 2.3.4)
r.POST("/mcp", middleware.IPWhiteList(), middleware.AuthRequired(), mcp.Handle)
r.POST("/mcp_message", middleware.IPWhiteList(), middleware.AuthRequired(), mcp.Handle)
The second defence — the IP whitelist — does not save the deployment, because the default IP whitelist ships empty, and the middleware treats an empty list as allow-all rather than deny-all. Any operator who installed nginx-ui and did not manually edit the allowlist exposed the unauthenticated endpoint to every network the service was reachable from.
Because mcp_message accepts the full MCP tool surface, the consequences are not limited to information disclosure. An unauthenticated caller can invoke tools that create, modify or delete nginx configuration files, trigger an automatic config reload, and restart the nginx service — the textbook definition of full web-server takeover. Pluto demonstrated the chain in two HTTP requests.
Why it matters
MCPwn is, as far as we can tell from public reporting, the first widely exploited CVE that targets the Model Context Protocol attack surface specifically — not a generic web bug that happens to live in an LLM stack. The vulnerable route exists because the project decided to expose admin operations to AI agents through MCP, and the auth gap exists in the MCP routing layer itself.
The pattern is going to repeat. MCP servers are landing inside developer tools, observability stacks, ticketing systems, IDEs and infrastructure dashboards at a pace that significantly exceeds the maturity of their authentication models. The Anthropic MCP specification leaves transport, auth and discovery loosely defined, and individual implementations have to wire those pieces themselves. The nginx-ui project did everything correctly on its legacy admin routes — the regression appears only on the MCP routes that were added later and reviewed less carefully.
The other lesson is about defaults. An IP allowlist that interprets an empty value as “allow everyone” is a foot-gun every administrator will eventually trip over. Default-deny is the only safe choice for any control whose explicit intent is to restrict access.
Defenses
Upgrade nginx-ui to 2.3.4 or later immediately. The patch (commit 413dc63) adds middleware.AuthRequired() to /mcp_message and ships a regression test asserting that both /mcp and /mcp_message return HTTP 403 without authentication. Active exploitation has been confirmed since late March 2026; assume any unpatched, internet-reachable nginx-ui has been touched and audit configuration history accordingly.
If you cannot patch immediately, the Pluto Security advisory documents two workarounds: add middleware.AuthRequired() to the /mcp_message route by hand, or change the IP allowlist semantics so an empty list means deny-all. Either is preferable to leaving the endpoint exposed.
Block the MCP endpoints at the reverse proxy until patched. A short NGINX or Envoy rule that returns 403 for POST /mcp and POST /mcp_message will hold the line for a few hours while you upgrade.
Audit your other MCP servers for the same class of bug. The pattern — administrative MCP routes added next to legacy routes, only some receiving auth middleware — generalises. Run a route-by-route check: for every MCP server in your inventory, list all registered endpoints, confirm each one is wrapped by authentication middleware, and write a test that asserts unauthenticated calls return 401/403. Treat MCP routes as production-grade admin surface, not as a debug add-on.
Move security decisions off opt-in IP allowlists. Any control whose absence means “allow everyone” is a regression waiting to happen. Default-deny, explicit allow.
Watch your logs for unauthenticated POSTs to /mcp_message with tool-call payloads referencing config_file, restart_nginx or reload_config. Successful exploitation leaves clear traces in nginx-ui’s request log and in nginx’s own reload events.
Status
| Item | Reference | Date | Notes |
|---|---|---|---|
| Discovery | Pluto Security | 2026-03-04 | Internal MCP route audit |
| Upstream report | nginx-ui maintainers notified | 2026-03-14 | Coordinated disclosure |
| Fixed release | nginx-ui 2.3.4 (commit 413dc63) | 2026-03-15 | Adds AuthRequired() + regression test |
| Active exploitation observed | Recorded Future | 2026-03 (late) | Within days of the patch |
| Added to VulnCheck KEV | VulnCheck | 2026-04-13 | Known exploited |
| Public disclosure | Pluto Security advisory + Rapid7 ETR | 2026-04-15 | ”MCPwn”, CVSS 9.8 |
| Affected versions | nginx-ui ≤ 2.3.3 (CVE record: ≤ 2.3.5) | — | Verify against your installed version |
| Patched versions | nginx-ui ≥ 2.3.4 | — | Upgrade and audit historical configs |
The takeaway is not that MCP is unsafe; it is that MCP endpoints inherit every web-application security obligation of the host that exposes them, and the rush to ship agent integrations is producing classic web bugs in places nobody is yet scanning. Patch nginx-ui, then go look at the rest of your MCP fleet before someone else does.
Sources
- → https://thehackernews.com/2026/04/critical-nginx-ui-vulnerability-cve.html
- → https://www.rapid7.com/blog/post/etr-cve-2026-33032-nginx-ui-missing-mcp-authentication/
- → https://www.picussecurity.com/resource/blog/cve-2026-33032-mcpwn-how-a-missing-middleware-call-in-nginx-ui-hands-attackers-full-web-server-takeover
- → https://pluto.security/blog/mcp-bug-nginx-security-vulnerability-cvss-9-8/
- → https://www.bleepingcomputer.com/news/security/critical-nginx-ui-auth-bypass-flaw-now-actively-exploited-in-the-wild/
- → https://securityaffairs.com/190841/hacking/cve-2026-33032-severe-nginx-ui-bug-grants-unauthenticated-server-access.html