highCVSS 8.8Vulnerability

CVE-2026-84316

## Summary `config.ValidateConfigFile` is the security control that blocks dangerous nginx directives (`js_*`, `perl_*`, `load_module` of njs/perl modules, `user root`). Its directive scanner is bypassable: it splits the config by newlines and inspects only the FIRST token of each line, but nginx separates directives with `;`, not newlines. Putting a benign directive first and the blocked directive after a `;` on the SAME line defeats every check. The `include` directive is also not on the denylist. As a result, an authenticated caller can inject the exact directives the hardening was meant to block, through EVERY path that calls the validator — `POST /api/configs` (add), the REST config modify endpoint (api/config/modify.go), the MCP `nginx_config_modify` tool, and the site/stream save paths (internal/site/save.go, internal/stream/save.go). On deployments where nginx has the njs/perl module (the official uozi/nginx-ui Docker image ships ngx_http_js_module.so), this leads to code execution in the nginx worker; with `user root` the workers run as root. This is distinct from the config_add gap (the MCP nginx_config_add tool not calling the validator at all): here the validator IS called and still bypassed, so fixing config_add does not fix this. ## Root cause (internal/config/validation.go, ValidateConfigDirectives) ```go for _, line := range bytes.Split(content, []byte("\n")) { // splits on \n only trimmed := strings.TrimSpace(string(line)) ... directive := firstDirectiveToken(trimmed) // first [a-zA-Z_]* of the line if directive == "user" && configuresRootWorkers(trimmed) { ... } // keyed on first token if directive == "load_module" && loadsRestrictedDynamicModule(...) { ... } // keyed on first token if _, blocked := blockedConfigDirectives[directive]; blocked { ... } // keyed on first token } ``` nginx parses `a 1; b 2;` on one line as two directives, but this scanner only ever sees `a`. `include` is

Properties

severity
high
summary
Nginx UI: nginx config directive denylist (ValidateConfigFile) is bypassable via same-line ";" separation → authenticated directive injection (RCE on the official image)
cvss_score
8.8
retrieved_at
2026-10-15T22:56:51+00:00
ghsa_published
2026-10-15T20:13:52Z
source_url
https://github.com/advisories/GHSA-cf23-7qxj-xmhr
ghsa_updated
2026-10-15T20:13:54Z
ghsa_id
GHSA-cf23-7qxj-xmhr
last_source
GitHub Advisory Database
cve_id
CVE-2026-84316
cvss_vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
signal_observed_at
2026-10-15T22:56:51+00:00
is_ghsa_only
false

Related Entities (5)

VULNERABLE_TO (1)

←[Software]go/github.com/0xJacky/Nginx-UI

AFFECTS (1)

→[Software]go/github.com/0xJacky/Nginx-UI

HAS_WEAKNESS (2)

→[Weakness]Improper Input Validation
→[Weakness]Incomplete List of Disallowed Inputs

REPORTED_BY (1)

→[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph

CVE-2026-84316 (CVSS 8.8) — Ninja Signal Threat Intelligence | Ninja Signal