CVE-2026-33032 - nginx-ui MCP auth bypass
nginx-ui exposed its Model Context Protocol integration through /mcp and
/mcp_message. The intended /mcp route required both IP allow-listing and
session authentication, but affected builds wired /mcp_message with only the
IP allow-list middleware. Because the default allow-list is empty and treated
as “allow all”, a network attacker can reach the message endpoint without
authentication and invoke MCP tools that read, create, modify, delete, reload,
or restart nginx configuration.
This is not a routine dependency bump. nginx-ui is an administrative control plane for reverse proxies, TLS settings, upstream routing, and service availability. A vulnerable deployment can let an unauthenticated network actor rewrite proxy behavior, disclose backend topology, capture headers through logging changes, or take nginx offline.
When to use it
- A repository deploys, vendors, builds, mirrors, images, configures, or documents nginx-ui or derived nginx-ui containers.
- MCP routes
/mcpor/mcp_messageexist, are enabled, or may be exposed on port9000, ingress, tunnels, remote admin hosts, or shared networks. - nginx-ui can read/write nginx config, reload/restart nginx, manage TLS, route upstream traffic, or expose backend topology.
- You need a bounded PR or triage note that verifies
/mcp_messagerequires authentication and hardens the admin/MCP network plane.
Inputs
- nginx-ui source/forks, Go modules, Dockerfiles, images, Compose/Helm/K8s/ Terraform/Ansible artifacts, reverse-proxy rules, SBOMs, generated manifests, smoke tests, and operator docs.
- Resolved binary/source version, route middleware shape, IP allow-list semantics, admin access layer, MCP enablement, nginx config paths, edge blocks, access logs, and credential rotation ownership.
- Available static route checks, route-auth tests, container builds, manifest renders, ingress policy tests, smoke tests that avoid MCP tool dispatch, SBOM, and dependency/security scans.
Affected versions
Advisory metadata is inconsistent, so this recipe requires verification rather than trusting one scanner row blindly:
- Vulnerable code shape:
mcp/router.goregisters/mcp_messagewithoutmiddleware.AuthRequired(). - Fixed code shape:
/mcp_messageis registered with bothmiddleware.IPWhiteList()andmiddleware.AuthRequired(), matching/mcp. - Conservative deployment target:
nginx-ui v2.3.6+or a vendor-patched build that proves the fixed code shape and passes the route-auth regression checks below. - Metadata caveat: GHSA/NVD records describe affected nginx-ui releases as
2.3.5and earlier and note that no public patch existed at publication, while upstream tags show the route middleware fixed by thev2.3.4source shape. Prefer source/binary verification plus a current hardened release over a bare version string.
Indicator-of-exposure
- The repository deploys, pins, vendors, builds, mirrors, or documents nginx-ui,
github.com/0xJacky/Nginx-UI,github.com/0xJacky/nginx-ui, or a derived container image. - nginx-ui listens on
9000, another non-loopback port, a Kubernetes Service, ingress, tunnel, remote admin host, shared lab network, or container port exposed beyond localhost. - MCP support is enabled or the deployed binary includes
/mcpand/mcp_messageroutes. - The nginx-ui config leaves the IP allow-list empty, broad, or controlled by untrusted deployment input.
- nginx-ui can write nginx config directories, reload nginx, restart nginx, or read generated site config and history files.
- The same nginx instance terminates sensitive applications, admin sessions, bearer-token traffic, tenant routes, internal APIs, or service credentials.
Quick checks:
rg -n "nginx-ui|Nginx-UI|0xJacky|uozi|/mcp_message|/mcp|mcp_message|IPWhiteList|AuthRequired|nginx_config_(add|modify|get|delete|enable)|restart_nginx|reload_nginx|9000|NGINX_UI" .
rg -n "nginx-ui|Nginx-UI|0xJacky|uozi|9000|mcp_message|mcp" Dockerfile* docker-compose*.yml .github deploy charts k8s helm terraform ansible scripts 2>/dev/null
Windows:
rg -n "nginx-ui|Nginx-UI|0xJacky|uozi|/mcp_message|/mcp|mcp_message|IPWhiteList|AuthRequired|nginx_config_(add|modify|get|delete|enable)|restart_nginx|reload_nginx|9000|NGINX_UI" .
rg -n "nginx-ui|Nginx-UI|0xJacky|uozi|9000|mcp_message|mcp" Dockerfile* docker-compose*.yml .github deploy charts k8s helm terraform ansible scripts
Do not invoke MCP tools, create nginx configs, rewrite routes, or probe a live production endpoint with JSON-RPC bodies during triage.
Remediation strategy
- Upgrade repository-controlled nginx-ui deployments to
v2.3.6+, or vendor a patch that addsmiddleware.AuthRequired()to/mcp_messageand proves that the running binary has the fixed route stack. - Refresh Helm values, Compose files, container tags, image digests, Terraform, Ansible, docs, SBOMs, generated manifests, and deployment evidence that name nginx-ui.
- Bind nginx-ui and its MCP endpoints to localhost or a tightly controlled admin network. Do not rely on an empty IP allow-list as a security control.
- Put nginx-ui behind authenticated admin access such as VPN, SSO-aware reverse
proxy, private ingress, or zero-trust access. Block
/mcpand/mcp_messageat the edge until the fixed route is deployed. - Add a route-auth regression test where this repository owns nginx-ui source,
a fork, a wrapper, or deployment smoke tests. The test should prove
unauthenticated
/mcp_messagerequests cannot reach MCP tool dispatch. - Audit nginx-ui access logs, nginx configuration history, generated
conf.d/sites-enabledfiles, and reload/restart history for unexpected changes. Rotate credentials if proxy config could have logged or redirected authorization headers.
The prompt
You are remediating CVE-2026-33032 / GHSA-h6c2-x2m2-mwhf, a critical nginx-ui
MCP authentication bypass on `/mcp_message`. Produce exactly one output:
- A reviewer-ready PR/change request that upgrades or vendor-patches nginx-ui,
proves the MCP message route requires authentication, hardens network
exposure, adds safe regression checks, refreshes generated artifacts, and
documents operator audit work, or
- TRIAGE.md if this repository does not control an affected nginx-ui
deployment, image, fork, wrapper, manifest, or admin-plane exposure.
## Rules
- Scope only CVE-2026-33032 / GHSA-h6c2-x2m2-mwhf and directly related nginx-ui
MCP route authentication and exposure controls.
- Treat nginx configs, TLS keys, auth headers, upstream names, session cookies,
admin routes, service credentials, audit logs, and tenant routing data as
sensitive.
- Do not invoke nginx-ui MCP tools, send JSON-RPC exploit bodies, write nginx
config files, reload/restart nginx, capture authorization headers, or test in
a live production session.
- Do not remove nginx-ui audit logging, TLS, route validation, or config
backups to make the finding disappear.
- Do not auto-merge.
## Steps
1. Inventory every nginx-ui reference controlled by this repository:
source forks, Go modules, Dockerfiles, Compose files, Helm charts,
Kubernetes manifests, Terraform, Ansible, install scripts, container tags,
image digests, SBOMs, generated manifests, operator docs, and smoke tests.
2. Determine the resolved nginx-ui version and binary source. Because public
advisory metadata disagrees on the patched version, verify the code shape:
`/mcp_message` must include `middleware.AuthRequired()` before it calls
`mcp.ServeHTTP`.
3. Search for network exposure of nginx-ui: port `9000`, host bindings,
Kubernetes Services and ingresses, load balancers, tunnels, devcontainers,
remote admin hosts, firewall rules, reverse-proxy paths, and public DNS.
4. Search nginx-ui auth settings for empty or broad IP allow-lists, weak admin
access, default credentials, unauthenticated reverse-proxy paths, and MCP
routes exposed separately from the web UI.
5. If this repository does not control nginx-ui source, deployment, image, or
admin routing, stop with `TRIAGE.md` listing checked files, the owning
platform team, the required fixed route shape, and the required deployment
target.
6. Upgrade controlled deployments to `nginx-ui v2.3.6+`, or vendor the minimal
route-auth patch if an upgrade is blocked. Refresh image digests, Helm
locks, Compose pins, SBOMs, generated manifests, docs, and dependency
reports.
7. Add or update regression checks:
- static source check: `/mcp_message` includes `AuthRequired()`;
- route test: unauthenticated `/mcp_message` cannot reach MCP tool dispatch;
- deployment check: nginx-ui is not bound to public interfaces by default;
- policy check: broad or empty allow-lists require an explicit reviewed
exception plus independent authentication;
- log check: test output omits config contents, headers, cookies, and
secrets.
8. Harden runtime exposure:
- bind nginx-ui to localhost or a private admin network;
- require SSO/VPN/zero-trust access before nginx-ui;
- block `/mcp` and `/mcp_message` at internet-facing edges;
- keep admin-plane ingress separate from tenant/application ingress;
- document any temporary containment and its owner.
9. Audit for possible compromise without attaching sensitive artifacts to the
PR:
- nginx-ui access logs around `/mcp` and `/mcp_message`;
- nginx config history and unexpected files under included config dirs;
- reload/restart events and config validation failures;
- injected `access_log`, `log_format`, `proxy_pass`, `auth_request`, or
redirect changes;
- unexpected reads of config history or upstream topology.
10. Add a PR body section named `CVE-2026-33032 operator actions` that states:
- nginx-ui versions and image digests before and after;
- whether the fixed `/mcp_message` route-auth shape was verified;
- where nginx-ui is reachable after the change;
- which admin access controls protect it;
- which logs and config-history locations operators should review;
- whether sessions, service credentials, TLS material, or upstream tokens
should be rotated because proxy config may have been changed.
11. Run available validation: unit tests for route middleware, source/static
checks, container build, Helm/Compose/Kubernetes render, policy tests,
smoke tests that do not invoke MCP tools, dependency/security scans, and
SBOM refresh.
12. Use PR title:
`fix(sec): remediate CVE-2026-33032 in nginx-ui MCP`.
## Stop conditions
- No nginx-ui source, image, deployment manifest, admin route, or operator doc
is controlled by this repository.
- The running nginx-ui instance is owned by another platform team or vendor;
document the owner, required route-auth shape, and required deployment target
in `TRIAGE.md`.
- The only available validation would require invoking MCP tools, changing live
nginx config, capturing headers, or reading production secrets.
- Upgrade requires a broader admin-plane migration or maintenance window the
agent cannot schedule.
- Validation fails for unrelated pre-existing reasons; document those failures
instead of broadening scope.
Verification - what the reviewer looks for
- No controlled nginx-ui deployment resolves to a binary where
/mcp_messagecan reach MCP tool dispatch without authentication. - The PR verifies the fixed route shape instead of relying only on a scanner’s version range.
- nginx-ui and MCP endpoints are not internet-facing unless protected by a reviewed admin access layer.
- Edge rules, ingress policy, and app-level auth agree on protecting both
/mcpand/mcp_message. - Operator notes cover config-history review and credential rotation without printing config contents, tokens, headers, or tenant routing details.
Output contract
- Reviewer-ready PR upgrading nginx-ui to
v2.3.6+or vendor-patching the/mcp_messageroute so authenticated middleware is verified in source and running artifact evidence. - Admin/MCP exposure reduced to localhost/private admin networks or protected
by SSO/VPN/zero-trust plus edge blocks for
/mcpand/mcp_messageuntil fixed runtime deployment is complete. - Safe regression checks proving unauthenticated
/mcp_messagecannot reach MCP tool dispatch and broad/empty allow-lists require reviewed auth layers. TRIAGE.mdwhen nginx-ui source, image, admin route, MCP exposure, or operator audit ownership is outside this repository.
Watch for
- Updating a container tag while Helm values, Compose files, image digests, or cached runner images still deploy an older nginx-ui build.
- Trusting an empty IP allow-list as a deny-by-default control. In affected code, empty means allow all.
- Protecting
/mcpat the reverse proxy while leaving/mcp_messagereachable. - Testing by calling real MCP tools against a production nginx-ui instance.
- Auditing only
nginx.confwhile nginx includes writable directories such asconf.d,sites-enabled, or custom managed paths.
Related recipes
- CVE-2026-11746 Central Dogma ZooKeeper replication secret takeover
- Browser agent boundary
- CVE intelligence intake gate
References
- GitHub Advisory: https://github.com/advisories/GHSA-h6c2-x2m2-mwhf
- Vendor advisory: https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-h6c2-x2m2-mwhf
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-33032
- Vulnerable route example: https://raw.githubusercontent.com/0xJacky/nginx-ui/v2.3.3/mcp/router.go
- Fixed route example: https://raw.githubusercontent.com/0xJacky/nginx-ui/v2.3.4/mcp/router.go
- nginx-ui v2.3.6 release: https://github.com/0xJacky/nginx-ui/releases/tag/v2.3.6