CVE-2026-33032 (MCPwn): How a Missing Middleware Call in nginx-ui Hands Attackers Full Web Server Takeover
| April 16, 2026
Key Points
- CVE-2026-33032 is a CVSS 9.8 authentication bypass in nginx-ui's Model Context Protocol (MCP) integration [1].
- The /mcp_message endpoint, which handles every destructive tool invocation, is missing the AuthRequired() middleware that its paired /mcp endpoint has.
- Any network-adjacent attacker can invoke 12 MCP tools (including nginx_config_add with auto-reload) with zero credentials, achieving complete nginx takeover in two HTTP requests.
- The flaw is actively exploited in the wild, added to the VulnCheck KEV list on April 13, 2026, and listed by Recorded Future's Insikt Group among the 31 most-exploited CVEs of March 2026.
- Patch to nginx-ui v2.3.4 or later immediately.
- Credit for discovery and responsible disclosure goes to security researcher Yotam Perkal [2].
Quick Answer Box
|
Field |
Value |
|
CVE ID |
CVE-2026-33032 |
|
Alias |
MCPwn |
|
CVSS v3.1 Score |
9.8 (Critical) |
|
Vector |
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
|
CWE |
CWE-306 — Missing Authentication for Critical Function |
|
Affected Product |
nginx-ui (all versions ≤ 2.3.3 with MCP enabled) |
|
Fixed In |
nginx-ui v2.3.4 (released March 15, 2026) |
|
Related CVE |
CVE-2026-27944 (CVSS 9.8, /api/backup credential exposure) |
|
Exploitation |
Confirmed in the wild (VulnCheck KEV, April 13, 2026) |
|
Exposed Instances |
~2,689 publicly reachable (Shodan) |
What Is CVE-2026-33032 (MCPwn)?
CVE-2026-33032 is a critical authentication bypass vulnerability in nginx-ui, the popular open-source web interface for managing nginx servers (11,000+ GitHub stars, 430,000+ Docker pulls).
The flaw lives in the tool's newly added Model Context Protocol (MCP) integration, the feature that lets AI assistants configure nginx on a user's behalf.
In short: the MCP router wires up two HTTP endpoints that both reach the same powerful handler, but only one of them checks authentication. The unauthenticated endpoint is the one that actually performs destructive operations.
An unauthenticated attacker on the same network can:
- Read any nginx configuration file
- Write arbitrary new config files and trigger automatic reload
- Restart the nginx process
- Enable, disable, or rename virtual host configurations
- Pivot into credential theft by injecting access_log directives that capture Authorization headers
- Forge admin JWTs after extracting the JwtSecret via the hijacked admin session
- Knock nginx offline with an invalid config
Because nginx-ui typically sits in front of production traffic, APIs, and internal services, compromise of nginx-ui is compromise of everything behind it.
Why CVE-2026-33032 Vulnerability Matters Right Now
Three factors elevate MCPwn above a typical web-app CVE:
It is already being exploited
- VulnCheck added CVE-2026-33032 to its Known Exploited Vulnerabilities (KEV) catalog on April 13, 2026.
- Recorded Future's Insikt Group ranked it 94/100 on its Risk Score and named it one of the 31 most-exploited CVEs of March 2026.
- This is placing it alongside actively weaponized flaws in Cisco, Microsoft, Google, and Citrix products.
The exploit is trivial
Two HTTP requests. No chained gadgets, no memory corruption, no sandbox escape.
A competent adversary can script the end-to-end attack in under fifty lines of Python.
The exposure is measurable and large
A Shodan favicon-hash search (http[.]favicon[.]hash:-1565173320) returns roughly 2,689 publicly reachable nginx-ui instances.
The largest clusters are in China, the United States, Indonesia, Germany, and Hong Kong, hosted across Alibaba Cloud, Oracle, Tencent, and DigitalOcean.
Every unpatched instance is a one-shot gateway to the nginx server behind it, and to every upstream service that nginx fronts.
Technical Root Cause: Two Endpoints, One Gate
nginx-ui uses the SSE (Server-Sent Events) transport from the mcp-go library. SSE is a two-endpoint design by construction:
- GET /mcp — opens a persistent event stream. The server assigns a session ID here and streams JSON-RPC responses back over it.
- POST /mcp_message?sessionId=<id> — the inbound channel where clients POST JSON-RPC tool invocations. Every destructive operation — config writes, nginx reloads, file reads — flows through this endpoint.
Here is the vulnerable router in nginx-ui v2.3.3 and earlier (mcp/router.go):
|
// Vulnerable -- v2.3.3 and earlier |
Look at the two routes side-by-side.
/mcp chains IPWhiteList() and AuthRequired(). /mcp_message chains IPWhiteList() only.
Both forward into the same mcp.ServeHTTP(c) handler, so /mcp_message inherits full tool-invocation power but drops the authentication check.
The attached diagram makes the gap visible at a glance: two endpoints, same handler, only one gate actually checks credentials. That single missing middleware reference is the entire vulnerability.
The Safety Net That Isn't: Fail-Open IP Whitelisting
With authentication gone, the only remaining control on /mcp_message is the IP whitelist. But the whitelist middleware fails open on a default (empty) configuration:
|
// internal/middleware/ip_whitelist.go |
Fresh installs, default configs, and any operator who simply never touched the IP whitelist setting are allowing every host on the network through. This is the textbook definition of a fail-open security control, and it turns a misconfiguration-class flaw into a default-case vulnerability.
Every unpatched nginx-ui with MCP enabled is exploitable out of the box.
The Attack Chain: Two Requests to Full Takeover
The diagram's lower half captures the flow cleanly. Here is the same flow in text, with protocol detail.

Figure 1. Diagram of CVE-2026-33032: nginx-ui's /mcp endpoint enforces authentication while /mcp_message does not, enabling unauthenticated nginx takeover in two HTTP requests.
Step 0 (optional prerequisite): Obtaining node_secret
MCP session establishment on GET /mcp still requires the node_secret query parameter. In a fully defaulted deployment this is a barrier, but one that collapses in two common scenarios:
- Chained with CVE-2026-27944 (CVSS 9.8, also unauthenticated) — the /api/backup endpoint in nginx-ui < 2.3.3 leaks the encryption keys needed to decrypt backups without authentication. An attacker can download a full system backup and extract user credentials, SSL private keys, nginx configurations, and the node_secret value itself.
- Internal/LAN attacker — on many deployments node_secret is present in environment variables, Docker Compose files, or Kubernetes secrets accessible from a compromised neighboring workload.
Either path delivers node_secret, which is all the attacker needs to move past step 1.
Step 1: Establish an SSE session
HTTP
|
GET /mcp?node_secret=<leaked_or_known_secret> HTTP/1.1 |
Server Response
|
event: endpoint |
Step 2: Invoke any MCP tool with no authentication
HTTP
|
POST /mcp_message?sessionId=4f4cdb82-152b-4c10-8f63-1df90e1e061f HTTP/1.1 |
No Authorization header. No JWT. No cookies. No node_secret on this request.
nginx_config_add writes the file and automatically triggers a configuration reload, config injection and activation in a single call.
The Full Tool Inventory an Attacker Gets
Destructive (7)
|
Tool |
Capability |
|
nginx_config_add |
Create config files + auto-reload nginx |
|
nginx_config_modify |
Modify any existing config |
|
nginx_config_enable |
Enable/disable sites |
|
nginx_config_rename |
Rename config files |
|
nginx_config_mkdir |
Create directories |
|
reload_nginx |
Reload configuration |
|
restart_nginx |
Restart the process |
Reconnaissance (5)
|
Tool |
Capability |
|
nginx_config_get |
Read any config file |
|
nginx_config_list |
Enumerate all configurations |
|
nginx_config_base_path |
Get config directory path |
|
nginx_config_history |
View config change history |
|
nginx_status |
Read server status |
Post-Exploitation Playbook: What Attackers Actually Do
Writing a demo page is the PoC.
The realistic attack tree is worse:
Traffic interception.
Rewrite upstream server blocks to proxy every request through an attacker-controlled endpoint.
The attacker now sees every request, response, session cookie, API token, and form submission that transits the nginx server.
Credential harvesting via log injection.
Inject a custom log_format that captures Authorization headers, plus an access_log directive scoped to the nginx-ui management path.
Administrators who subsequently log into nginx-ui leak their JWTs into a log file the attacker can then read back via nginx_config_get on the log path (or via a symlinked location served by the injected server block).
Persistence via JwtSecret theft.
Once the attacker has captured one admin JWT, they call the authenticated nginx-ui settings API and extract the JwtSecret.
From there they can forge admin JWTs for any user indefinitely; persistence that survives config rollback, because the secret itself is now attacker-known.
Reconnaissance and lateral movement.
nginx_config_list + nginx_config_get expose the entire internal service topology: upstream hostnames, backend ports, TLS certificate paths, internal service names.
This is a map of the environment, handed over unauthenticated.
Denial of service.
Write a syntactically invalid config, call reload_nginx, nginx refuses to reload or crashes on restart.
Everything behind it goes dark.
Detection Guidance
If you run nginx-ui and cannot immediately patch, hunt for the following indicators.
Network-layer indicators
- Any POST request to /mcp_message from an IP outside your operator allow-list
- GET /mcp?node_secret=... requests from unexpected source IPs
- Long-lived SSE connections to /mcp from hosts that are not your AI/automation tooling
Host-layer indicators on the nginx-ui server
- New or modified files under conf.d/, sites-enabled/, sites-available/ that you did not deploy via your normal change-management pipeline
- New entries in the nginx-ui config change history (nginx_config_history records) without a corresponding ticket or PR
- Unexpected reloads in nginx error logs (signal process started) during windows when no legitimate change was pushed
- Unusual log_format or access_log directives — especially any that reference $http_authorization, $http_cookie, or full request bodies
Identity-layer indicators
- nginx-ui admin logins from unfamiliar IPs or user-agents
- JWTs with anomalous iat/exp skew (suggesting forged tokens after JwtSecret theft)
Remediation Plan for CVE-2026-33032 In Priority Order
Priority 1: Update to nginx-ui v2.3.4 or later.
This is the only complete fix. Commit 413dc63 adds the missing AuthRequired()middleware and ships a regression test (mcp/router_test.go) that asserts both /mcp and /mcp_message return HTTP 403 without authentication. If the test had existed originally, the CVE would not exist.
Priority 2: If you cannot patch right now, apply one or both of these emergency mitigations and treat them as stopgaps, not solutions:
- Disable MCP entirely if you are not actively using it.
- Populate the IP whitelist with an explicit allow-list of trusted hosts. Never leave it empty — empty means allow-all.
- Add middleware.AuthRequired() to the /mcp_message route manually if you build from source.
Priority 3: Rotate everything that might have been exposed. If you have any reason to suspect exploitation, treat the following as compromised: the nginx-ui JwtSecret, all nginx-ui user credentials, any SSL private keys that were managed through nginx-ui, and the node_secret. Also rotate credentials for any upstream services nginx fronted — assume traffic interception.
Priority 4: Audit conf.d/, sites-enabled/, and nginx access-log formats for unauthorized modifications since MCP was enabled.
Priority 5: Restrict network exposure. nginx-ui's management interface (default port 9000) should not be reachable from the public internet.
The 2,600+ Shodan-exposed instances are failing this rule; do not be one of them.
How Picus Helps Simulate CVE-2026-33032 Vulnerability Exploitation Attacks?
We also strongly suggest simulating the nginx-ui CVE-2026-33032 (MCPwn) vulnerability to test the effectiveness of your security controls against sophisticated cyber attacks using the Picus Security Validation Platform. You can also test your defenses against other vulnerability exploitation attacks, such as regreSSHion, Citrix Bleed, and Follina, within minutes with a 14-day free trial of the Picus Platform.
Picus Threat Library includes the following threats for nginx-ui CVE-2026-33032 (MCPwn) exploitation attacks:
|
Threat ID |
Threat Name |
Attack Module |
|
69689 |
NGINX UI Web Attack Campaign |
Web Application |
Start simulating emerging threats today and get actionable mitigation insights with a 14-day free trial of the Picus Security Validation Platform.
References
[1] “NVD - CVE-2026-33032.” Available: https://nvd.nist.gov/vuln/detail/CVE-2026-33032. [Accessed: Apr. 16, 2026]
[2] Y. Perkal, “MCPwn: A CVSS 9.8 One-Line MCP Bug That Hands Over Your Nginx to Anyone on the Network – Actively Exploited in the Wild,” Pluto Security, Apr. 15, 2026. Available: https://pluto.security/blog/mcp-bug-nginx-security-vulnerability-cvss-9-8/. [Accessed: Apr. 16, 2026]
