CVE-2026-107810: Nginx UI Backup Restore Follows Crafted Symlinks Vulnerability
HIGHCVE-2026-107810 is a HIGH (CVSS 8.1) backup restore follows crafted symlinks vulnerability (CWE-59: Improper Link Resolution Before File Access ('Link Following')) affecting Nginx UI libraries in the Go ecosystem. The issue involves backup restore follows crafted symlinks into the live nginx configuration path before restore flags are applied. Remediation is available by upgrading affected packages to version 1.9.10-0.20260728074146-a467ed652591.
CVE-2026-107810 at a Glance
Security Impact
CVSS: 8.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H).
How to Fix CVE-2026-107810
To remediate this vulnerability, upgrade all affected Nginx UI dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/0xJacky/Nginx-UI to 1.9.10-0.20260728074146-a467ed652591
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/0xJacky/Nginx-UI
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-107810, inspect your project dependencies for Nginx UI:
inspect dependencies for github.com/0xJacky/Nginx-UI
Analyze the terminal output to locate any version of Nginx UI in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.9.10-0.20260728074146-a467ed652591), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-59: Improper Link Resolution Before File Access ('Link Following'), where the product attempts to access a file based on the filename, but it does not properly prevent that filename from identifying a link or shortcut that resolves to an unintended resource. In Nginx UI, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-107810 Affected Nginx UI Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/0xJacky/Nginx-UI
|
Go |
≥ 1.9.10-0.20250517140552-daee3ac7ade1
< 1.9.10-0.20260728074146-a467ed652591
|
1.9.10-0.20260728074146-a467ed652591
|
References
Frequently Asked Questions
What is CVE-2026-107810?
Which Nginx UI versions are affected?
What version fixes CVE-2026-107810?
Is github.com/0xJacky/Nginx-UI affected?
What is the CVSS score of CVE-2026-107810?
What CWE is associated with CVE-2026-107810?
How can I check Go dependencies for CVE-2026-107810?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-p8v3-89rh-jxc7",
"modified" : "2026-10-09T17:07:05Z",
"published" : "2026-10-09T17:07:05Z",
"aliases" : [ "CVE-2026-107810" ],
"summary" : "Nginx UI: Backup restore follows crafted symlinks into the live Nginx configuration path before restore flags are applied",
"details" : "### Summary\nAn authenticated user who can create and restore a backup can craft a valid backup archive that causes the restore staging process to write attacker-controlled files into the live Nginx configuration path even when both `restore_nginx` and `restore_nginx_ui` are set to `false`.\n\n### Details\nThe restore flow always extracts the outer archive, verifies the manifest, decrypts `nginx-ui.zip` and `nginx.zip`, and extracts both inner archives before it decides whether `RestoreNginx` or `RestoreNginxUI` should be applied. The zip extractor explicitly allows absolute symlinks when the link target is under `nginx.GetConfPath()` or `nginx.GetModulesPath()`. Later regular-file entries are then created with `os.OpenFile()` on the symlinked path, which follows the symlink and writes into the live path.\n\nRelevant code paths:\n- [internal/backup/restore.go](/home/kali/Desktop/bounty/nginx-ui/internal/backup/restore.go:39)\n- [internal/backup/restore.go](/home/kali/Desktop/bounty/nginx-ui/internal/backup/restore.go:79)\n- [internal/backup/restore.go](/home/kali/Desktop/bounty/nginx-ui/internal/backup/restore.go:204)\n- [internal/backup/restore.go](/home/kali/Desktop/bounty/nginx-ui/internal/backup/restore.go:286)\n- [api/backup/restore.go](/home/kali/Desktop/bounty/nginx-ui/api/backup/restore.go:31)\n- [api/backup/backup.go](/home/kali/Desktop/bounty/nginx-ui/api/backup/backup.go:15)\n\nThis means the restore trust boundary is broken during extraction. A restore request that explicitly opted out of restoring either Nginx or Nginx UI can still modify the live Nginx configuration tree during staging.\n\n### PoC\nI verified this locally in an isolated environment with a temporary package-level harness that exercised the real `Backup()` and `Restore()` implementations.\n\nWhat the executed test did:\n1. Created a temporary `app.ini`, database file, and a temporary live Nginx config directory.\n2. Called the real `Backup()` implementation to obtain a valid backup archive plus AES key/IV.\n3. Extracted the outer backup, decrypted `nginx.zip`, replaced it with a crafted zip containing:\n - a symlink entry `link -> <live nginx conf dir>`\n - a later regular file entry `link/poc.conf`\n4. Recomputed `manifest.json` size/hash values for the modified encrypted `nginx.zip` and re-signed `manifest.sig` with the expected signing key derived from the AES key.\n5. Repacked the outer archive and called the real `Restore()` implementation with:\n - `RestoreNginx: false`\n - `RestoreNginxUI: false`\n6. Verified that `<live nginx conf dir>/poc.conf` was created anyway.\n\nObserved result from the actual local verification:\n- The crafted restore completed successfully with both restore flags set to `false`.\n- The asserted sink was the existence and content of the live-path file written during restore staging.\n\n### Impact\nAny deployment that allows an authenticated user to create and restore backups is affected. A crafted restore archive can modify the live Nginx configuration path before either restore toggle is honored. This can lead to persistent configuration injection, denial of service on a later reload, or other follow-on impact depending on what files the deployment later consumes from the modified path.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/0xJacky/Nginx-UI"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "1.9.10-0.20250517140552-daee3ac7ade1"
}, {
"fixed" : "1.9.10-0.20260728074146-a467ed652591"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-p8v3-89rh-jxc7"
}, {
"type" : "WEB",
"url" : "https://github.com/0xJacky/nginx-ui/commit/a467ed652591fc0cd1b466a1ec751b493faef9f7"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/0xJacky/nginx-ui"
}, {
"type" : "WEB",
"url" : "https://github.com/0xJacky/nginx-ui/releases/tag/v2.5.0"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-59", "CWE-61" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-10-09T17:07:05Z",
"nvd_published_at" : null
}
}