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)
AFFECTS (1)
HAS_WEAKNESS (2)
REPORTED_BY (1)
Explore deeper with Ninja Signal's threat intelligence graph