CVE-2024-22198: Nginx-UI: command injection via settings API

GHSA-8r25-68wm-jw35 HIGH
Published January 11, 2024
CISO Take

Nginx-UI, a web admin panel for Nginx that ships with a built-in OpenAI-powered assistant, lets any authenticated user overwrite the 'Terminal Start Command' setting through an unauthorized API call, then trigger it to spawn an arbitrary command as root when the web terminal is opened. This is a low-bar authenticated RCE — the API endpoint checks for a valid JWT but never checks role, so a freshly self-registered, zero-privilege account can pivot straight to root on the host or container. With 4,631 downstream dependents and an EPSS score in the top 10th percentile for exploitation likelihood, exposure is meaningful even though this isn't in CISA KEV and no public exploit or Nuclei template exists yet. Patch to the version at or after commit 827e76c46e63 (post v1.9.10-beta.7-era build), and in the meantime restrict who can create accounts on internet-facing Nginx-UI instances and audit `/api/settings` calls and web terminal sessions for unexpected `start_cmd` values.

Sources: NVD EPSS GitHub Advisory ATLAS

What is the risk?

High practical risk despite the 'only' 7.1 CVSS score: exploitation requires just a low-privilege authenticated session (self-registration is often open by default), no user interaction beyond the attacker's own actions, and results in full root command execution. The missing authorization-role check on a settings-write endpoint is a textbook broken-access-control flaw that is trivial to exploit once known — a single crafted POST request plus opening the built-in web terminal. No CISA KEV listing or public exploit/Nuclei template currently exists, which caps near-term mass exploitation, but the EPSS top-10% percentile signals meaningful real-world interest, and any instance that allows open self-registration or exposes the admin panel to untrusted networks is immediately at risk.

How does the attack unfold?

Initial Access
Attacker obtains or self-registers a low-privilege authenticated account on the Nginx-UI instance.
AML.T0012
Privilege Escalation
Attacker sends an unauthorized POST to /api/settings overwriting the Terminal Start Command since the endpoint lacks role-based checks.
AML.T0047
Execution
Attacker opens the web-based terminal, triggering the poisoned start_cmd and spawning an arbitrary shell.
AML.T0050
Impact
Attacker gains a root shell on the host or container, enabling full compromise, lateral movement, and information disclosure.

What systems are affected?

Package Ecosystem Vulnerable Range Patched
OpenAI Node go < 1.9.10-0.20231219184941-827e76c46e63 1.9.10-0.20231219184941-827e76c46e63
11.1K 1.0K dependents Pushed 3d ago 64% patched ~301d to patch Full package profile →

Do you use OpenAI Node? You're affected.

How severe is it?

CVSS 3.1
7.1 / 10
EPSS
4.1%
chance of exploitation in 30 days
Higher than 90% of all CVEs
Exploitation Status
No known exploitation
Sophistication
Trivial

What is the attack surface?

AV AC PR UI S C I A
AV Network
AC High
PR Low
UI None
S Unchanged
C High
I High
A Low

What should I do?

1 step
  1. 1) Upgrade to the patched version at or after commit 827e76c46e63c52114a62a899f61313039c754e3 (fixes GHSA-8r25-68wm-jw35) — confirm via go.mod/binary version against GO-2024-2462. 2) Until patched, disable open self-registration on Nginx-UI instances and restrict the admin panel to a trusted network/VPN or behind an additional auth layer (SSO/mTLS). 3) Audit POST /api/settings request logs for unexpected server.start_cmd values (anything other than the default shell). 4) Monitor web terminal / PTY session creation events for anomalous process spawns as root. 5) Enforce least-privilege container runtime (non-root user, read-only filesystem) so a compromised start_cmd cannot escalate beyond the container. 6) Treat any Nginx-UI instance with its OpenAI integration configured as a higher-value target and review its credentials/token scope after patching.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

ISO 42001
A.8 - AI system security controls
NIST AI RMF
MANAGE 4.1 - Risks and benefits are regularly monitored based on contextual factors including AI system security

Frequently Asked Questions

What is CVE-2024-22198?

Nginx-UI, a web admin panel for Nginx that ships with a built-in OpenAI-powered assistant, lets any authenticated user overwrite the 'Terminal Start Command' setting through an unauthorized API call, then trigger it to spawn an arbitrary command as root when the web terminal is opened. This is a low-bar authenticated RCE — the API endpoint checks for a valid JWT but never checks role, so a freshly self-registered, zero-privilege account can pivot straight to root on the host or container. With 4,631 downstream dependents and an EPSS score in the top 10th percentile for exploitation likelihood, exposure is meaningful even though this isn't in CISA KEV and no public exploit or Nuclei template exists yet. Patch to the version at or after commit 827e76c46e63 (post v1.9.10-beta.7-era build), and in the meantime restrict who can create accounts on internet-facing Nginx-UI instances and audit `/api/settings` calls and web terminal sessions for unexpected `start_cmd` values.

Is CVE-2024-22198 actively exploited?

No confirmed active exploitation of CVE-2024-22198 has been reported, but organizations should still patch proactively.

How to fix CVE-2024-22198?

1) Upgrade to the patched version at or after commit 827e76c46e63c52114a62a899f61313039c754e3 (fixes GHSA-8r25-68wm-jw35) — confirm via `go.mod`/binary version against GO-2024-2462. 2) Until patched, disable open self-registration on Nginx-UI instances and restrict the admin panel to a trusted network/VPN or behind an additional auth layer (SSO/mTLS). 3) Audit `POST /api/settings` request logs for unexpected `server.start_cmd` values (anything other than the default shell). 4) Monitor web terminal / PTY session creation events for anomalous process spawns as root. 5) Enforce least-privilege container runtime (non-root user, read-only filesystem) so a compromised start_cmd cannot escalate beyond the container. 6) Treat any Nginx-UI instance with its OpenAI integration configured as a higher-value target and review its credentials/token scope after patching.

What systems are affected by CVE-2024-22198?

This vulnerability affects the following AI/ML architecture patterns: AI-enabled admin/DevOps tooling, model serving (reverse-proxied inference endpoints).

What is the CVSS score for CVE-2024-22198?

CVE-2024-22198 has a CVSS v3.1 base score of 7.1 (HIGH). The EPSS exploitation probability is 4.09%.

What is the AI security impact?

Affected AI Architectures

AI-enabled admin/DevOps toolingmodel serving (reverse-proxied inference endpoints)

MITRE ATLAS Techniques

AML.T0012 Valid Accounts
AML.T0047 AI-Enabled Product or Service
AML.T0050 Command and Scripting Interpreter

Compliance Controls Affected

ISO 42001: A.8
NIST AI RMF: MANAGE 4.1

What are the technical details?

Original Advisory

### Summary Nginx-UI is a web interface to manage Nginx configurations. It is vulnerable to arbitrary command execution by abusing the configuration settings. ### Details The `Home > Preference` page exposes a list of system settings such as `Run Mode`, `Jwt Secret`, `Node Secret` and `Terminal Start Command`. The latter is used to specify the command to be executed when a user opens a terminal from the web interface. While the UI doesn't allow users to modify the `Terminal Start Command` setting, it is possible to do so by sending a request to the [API](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/api/system/router.go#L13). ```go func InitPrivateRouter(r *gin.RouterGroup) { r.GET("settings", GetSettings) r.POST("settings", SaveSettings) ... } ``` The [`SaveSettings`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/api/system/settings.go#L18) function is used to save the settings. It is protected by the [`authRequired`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/router/middleware.go#L45) middleware, which requires a valid JWT token or a `X-Node-Secret` which must equal the `Node Secret` configuration value. However, given the lack of authorization roles, any authenticated user can modify the settings. The `SaveSettings` function is defined as follows: ```go func SaveSettings(c *gin.Context) { var json struct { Server settings.Server `json:"server"` ... } ... settings.ServerSettings = json.Server ... err := settings.Save() ... } ``` The `Terminal Start Command` setting is stored as [`settings.ServerSettings.StartCmd`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/settings/server.go#L12). By spawning a terminal with [`Pty`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/api/terminal/pty.go#L11), the `StartCmd` setting is used: ```go func Pty(c *gin.Context) { ... p, err := pty.NewPipeLine(ws) ... } ``` The [`NewPipeLine`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/internal/pty/pipeline.go#L29) function is defined as follows: ```go func NewPipeLine(conn *websocket.Conn) (p *Pipeline, err error) { c := exec.Command(settings.ServerSettings.StartCmd) ... ``` This issue was found using CodeQL for Go: [Command built from user-controlled sources](https://codeql.github.com/codeql-query-help/go/go-command-injection/). #### Proof of Concept > Based on [this setup](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/README.md?plain=1#L210) using `uozi/nginx-ui:v2.0.0-beta.7`. 1. Login as a newly created user. 2. Send the following request to modify the settings with `"start_cmd":"bash"` : ```http POST /api/settings HTTP/1.1 Host: 127.0.0.1:8080 Content-Length: 512 Authorization: <<JWT TOKEN>> Content-Type: application/json {"nginx":{"access_log_path":"","error_log_path":"","config_dir":"","pid_path":"","test_config_cmd":"","reload_cmd":"","restart_cmd":""},"openai":{"base_url":"","token":"","proxy":"","model":""},"server":{"http_host":"0.0.0.0","http_port":"9000","run_mode":"debug","jwt_secret":"...","node_secret":"...","http_challenge_port":"9180","email":"...","database":"foo","start_cmd":"bash","ca_dir":"","demo":false,"page_size":10,"github_proxy":""}} ``` 3. Open a terminal from the web interface and execute arbitrary commands as `root`: ``` root@1de46642d108:/app# id uid=0(root) gid=0(root) groups=0(root) ``` ### Impact This issue may lead to authenticated Remote Code Execution, Privilege Escalation, and Information Disclosure.

Exploitation Scenario

An attacker registers (or already holds) a low-privilege account on an internet-facing Nginx-UI instance. Authenticated with a valid JWT, they send a POST request to `/api/settings` overwriting only the `server.start_cmd` field to `bash` (or a reverse-shell one-liner) — the endpoint's authorization check validates the token but never verifies the caller has admin rights. The attacker then opens the built-in web terminal feature, which spawns a PTY using the now-poisoned `start_cmd`, handing them an interactive root shell on the underlying host or container (`uid=0(root)`). From there they can pivot to any co-located services, including AI inference backends or reverse-proxied model APIs sitting behind the same Nginx-UI instance.

Weaknesses (CWE)

CWE-77 — Improper Neutralization of Special Elements used in a Command ('Command Injection'): The product constructs all or part of a command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended command when it is sent to a downstream component.

  • [Architecture and Design] If at all possible, use library calls rather than external processes to recreate the desired functionality.
  • [Implementation] If possible, ensure that all external commands called from the program are statically created.

Source: MITRE CWE corpus.

CVSS Vector

CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L

Timeline

Published
January 11, 2024
Last Modified
July 6, 2026
First Seen
July 6, 2026

Related Vulnerabilities