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 /mcp or /mcp_message exist, are enabled, or may be exposed on port 9000, 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_message requires 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.go registers /mcp_message without middleware.AuthRequired().
  • Fixed code shape: /mcp_message is registered with both middleware.IPWhiteList() and middleware.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.5 and earlier and note that no public patch existed at publication, while upstream tags show the route middleware fixed by the v2.3.4 source 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 /mcp and /mcp_message routes.
  • 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 adds middleware.AuthRequired() to /mcp_message and 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 /mcp and /mcp_message at 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_message requests cannot reach MCP tool dispatch.
  • Audit nginx-ui access logs, nginx configuration history, generated conf.d/sites-enabled files, 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_message can 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 /mcp and /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_message route 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 /mcp and /mcp_message until fixed runtime deployment is complete.
  • Safe regression checks proving unauthenticated /mcp_message cannot reach MCP tool dispatch and broad/empty allow-lists require reviewed auth layers.
  • TRIAGE.md when 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 /mcp at the reverse proxy while leaving /mcp_message reachable.
  • Testing by calling real MCP tools against a production nginx-ui instance.
  • Auditing only nginx.conf while nginx includes writable directories such as conf.d, sites-enabled, or custom managed paths.

References