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)` = `/` — 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:"omit
- Products
- github.com/0xJacky/Nginx-UI
- Affected versions
- Not specified
- Fixed versions
- 1.9.10-0.20260728114330-580585516dd8
- CVEs
- CVE-2026-107812
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 31 Oct 2026, 08:44 UTC · Revision 1
Source evidence
Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM
core-osv · Original sourcePublished 9 Oct 2026, 17:08 UTC
## 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)` = `/` — 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:"omit
osv:GHSA-662p-52hx-cmh2
github.com/0xJacky/Nginx-UI
Fixed versions: 1.9.10-0.20260728114330-580585516dd8
Complete source record
{
"id": "1639195ae4f4d981b6124b32ad38622d9725632e27d9fe8e95bd4c9a5deb2f69",
"url": "https://osv.dev/vulnerability/GHSA-662p-52hx-cmh2",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "Nginx UI: Self-upgrade runs an unsigned binary verified only by a same-origin digest → RCE via a compromised mirror or MITM",
"summary": "## 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)` = `/` — 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:\"omit",
"evidence": "osv:GHSA-662p-52hx-cmh2",
"products": [
{
"name": {
"value": "github.com/0xJacky/Nginx-UI",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "1.9.10-0.20260728114330-580585516dd8",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
}
],
"severity": "high",
"structured": {
"id": "GHSA-662p-52hx-cmh2",
"aliases": [
"CVE-2026-107812",
"GHSA-662p-52hx-cmh2",
"GO-2026-6705"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H"
}
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "1.9.10-0.20250517140552-daee3ac7ade1"
},
{
"fixed": "1.9.10-0.20260728114330-580585516dd8"
}
]
}
],
"package": {
"name": "github.com/0xJacky/Nginx-UI",
"purl": "pkg:golang/github.com/0xJacky/Nginx-UI",
"ecosystem": "Go"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-662p-52hx-cmh2/GHSA-662p-52hx-cmh2.json"
}
}
],
"modified": "2026-10-19T21:40:58.486568803Z",
"provider": "osv",
"references": [
"https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-662p-52hx-cmh2",
"https://github.com/0xJacky/nginx-ui/commit/580585516dd87a8b176bcdac258db70c3b64b7ec",
"https://github.com/0xJacky/nginx-ui",
"https://github.com/0xJacky/nginx-ui/releases/tag/v2.5.0"
],
"provider_metadata": {
"cwe_ids": [
"CWE-494"
],
"severity": "HIGH",
"github_reviewed": true,
"nvd_published_at": null,
"github_reviewed_at": "2026-10-09T17:08:21Z"
}
},
"related_cves": [
{
"value": "CVE-2026-107812",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 376763,
"published_at": "2026-10-09T17:08:21+00:00"
}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
core-osv · Original sourcePublished 19 Oct 2026, 21:08 UTC
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
osv:GO-2026-6705
github.com/0xJacky/Nginx-UI
Fixed versions: 1.9.10-0.20260728114330-580585516dd8
Complete source record
{
"id": "00bbae8a84bce051476b5243414cb4e42e529b59fae0c8de0444ad86cc12ad2f",
"url": "https://osv.dev/vulnerability/GO-2026-6705",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "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",
"summary": "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",
"evidence": "osv:GO-2026-6705",
"products": [
{
"name": {
"value": "github.com/0xJacky/Nginx-UI",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "1.9.10-0.20260728114330-580585516dd8",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
}
],
"severity": "unknown",
"structured": {
"id": "GO-2026-6705",
"aliases": [
"CVE-2026-107812",
"GHSA-662p-52hx-cmh2",
"GO-2026-6705"
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "1.9.10-0.20250517140552-daee3ac7ade1"
},
{
"fixed": "1.9.10-0.20260728114330-580585516dd8"
}
]
}
],
"package": {
"name": "github.com/0xJacky/Nginx-UI",
"purl": "pkg:golang/github.com/0xJacky/Nginx-UI",
"ecosystem": "Go"
},
"database_specific": {
"source": "https://vuln.go.dev/ID/GO-2026-6705.json"
},
"ecosystem_specific": {}
}
],
"modified": "2026-10-19T21:31:49.314770793Z",
"provider": "osv",
"references": [
"https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-662p-52hx-cmh2",
"https://github.com/0xJacky/nginx-ui/commit/580585516dd87a8b176bcdac258db70c3b64b7ec",
"https://github.com/0xJacky/nginx-ui/releases/tag/v2.5.0"
],
"provider_metadata": {
"url": "https://pkg.go.dev/vuln/GO-2026-6705",
"review_status": "UNREVIEWED"
}
},
"related_cves": [
{
"value": "CVE-2026-107812",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": null
},
"source_id": "core-osv",
"document_id": 376686,
"published_at": "2026-10-19T21:08:26+00:00"
}