GitHub Advisoryadvisory · Go

GHSA-p8v3-89rh-jxc7 Nginx UI: Backup restore follows crafted symlinks into the live Nginx configuration path before restore flags are applied

HIGH Published 2026-10-09 Modified 2026-10-09 Official page ↗
Aliases
CVE-2026-107810
Ecosystem
Go
Packages
github.com/0xJacky/Nginx-UI
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H
Weaknesses
CWE-59, CWE-61
Reviewed
2026-10-09

Affected packages

• Go github.com/0xJacky/Nginx-UI: >= 1.9.10-0.20250517140552-daee3ac7ade1, < 1.9.10-0.20260728074146-a467ed652591 → fixed in 1.9.10-0.20260728074146-a467ed652591

Description

Summary An 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`. Details The 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. Relevant code paths: • internal/backup/restore.go • internal/backup/restore.go • internal/backup/restore.go • internal/backup/restore.go • api/backup/restore.go • api/backup/backup.go This 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. PoC I verified this locally in an isolated environment with a temporary package-level harness that exercised the real `Backup()` and `Restore()` implementations. What the executed test did: 1. Created a temporary `app.ini`, database file, and a temporary live Nginx config directory. 2. Called the real `Backup()` implementation to obtain a valid backup archive plus AES key/IV. 3. Extracted the outer backup, decrypted `nginx.zip`, replaced it with a crafted zip containing: • a symlink entry `link -> ` • a later regular file entry `link/poc.conf` 4. 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. 5. Repacked the outer archive and called the real `Restore()` implementation with: • `RestoreNginx: false` • `RestoreNginxUI: false` 6. Verified that `/poc.conf` was created anyway. Observed result from the actual local verification: • The crafted restore completed successfully with both restore flags set to `false`. • The asserted sink was the existence and content of the live-path file written during restore staging. Impact Any 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.

Related

Alias · CVE (1)

  • CVE-2026-107810 Nginx UI is a web user interface for the Nginx web server. vulnerability

Weakness · CWE (2)

  • CWE-59 Improper Link Resolution Before File Access weakness
  • CWE-61 UNIX Symbolic Link (Symlink) Following weakness

References