CVE-2026-84320
Nginx UI: Auto backup name allows path traversal outside validated storage path
Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.3, Nginx UI validates an automatic backup's storage_path, but AutoBackup.GetName returns a user-controlled name without rejecting path separators or parent-directory components, and downstream filename formatting embeds that result in the final archive filename. An authenticated user who can create or modify an automatic backup can cause filepath.Join to resolve the generated archive path outside the validated storage directory, allowing backup archives to be written with the Nginx UI process privileges. For encrypted configuration backups, the adjacent encryption key file can also be written outside the validated directory. This issue is fixed in version 2.4.3.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
6.3
Nginx UI: Auto backup name allows path traversal outside validated storage path
Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.3, Nginx UI validates an automatic backup's storage_path, but AutoBackup.GetName returns a user-controlled name without rejecting path separators or parent-directory components, and downstream filename formatting embeds that result in the final archive filename. An authenticated user who can create or modify an automatic backup can cause filepath.Join to resolve the generated archive path outside the validated storage directory, allowing backup archives to be written with the Nginx UI process privileges. For encrypted configuration backups, the adjacent encryption key file can also be written outside the validated directory. This issue is fixed in version 2.4.3.
- Record
CVE-2026-84320- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
EUVDEUVD-2026-97860
6.3
Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.3, Nginx UI validates an automatic backup's storage_path, but AutoBackup.GetName returns a user-controlled name without rejecting path separators or parent-directory components, and downstream filename formatting embeds that result in the final archive filename. An authenticated user who can create or modify an automatic backup can cause filepath.Join to resolve the generated archive path outside the validated storage directory, allowing backup archives to be written with the Nginx UI process privileges. For encrypted configuration backups, the adjacent encryption key file can also be written outside the validated directory. This issue is fixed in version 2.4.3.
- Record
EUVD-2026-97860- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-jrq7-xrjx-pcfw
6.3
Nginx UI: Auto backup name allows path traversal outside validated storage path
Summary
Nginx UI validates backup_path and storage_path against the administrator-defined backup.GrantedAccessPath boundary, but the final auto-backup output filename is built from the user-controlled auto-backup name without stripping path separators or .. components.
An authenticated user who can create or modify an auto-backup task can set a name such as task/../../../escaped. The configured storage_path still passes validation because it is inside GrantedAccessPath, but the generated backup path escapes that storage directory when filepath.Join(storage_path, filename) resolves the embedded traversal sequence.
This bypasses the documented backup path boundary and allows backup archives, and for encrypted configuration backups the adjacent .key file, to be written outside the intended storage directory with the Nginx UI process privileges.
Affected Versions
- Current
devbranch commit checked:4948fba8744e82c3d7003f68ee164e9f49421066 - Latest release checked:
v2.3.10, published 2026-04-28 - The vulnerable filename construction is present in both current
devandv2.3.10.
Security Boundary
The project documentation describes backup.GrantedAccessPath as the critical security boundary for backup operations. It says the setting:
- restricts backup operations to explicitly authorized directories,
- prevents unauthorized access to sensitive system directories,
- enforces administrator-defined boundaries,
- normalizes paths to prevent traversal attempts.
That boundary is enforced for the configured storage_path, but not for the final path after the backup name is appended.
Root Cause
model.AutoBackup.GetName() only trims whitespace and replaces spaces:
func (a *AutoBackup) GetName() string {
return strings.ReplaceAll(strings.TrimSpace(a.Name), " ", "_")
}
The result is then embedded directly into filenames:
filename := fmt.Sprintf("%s_%d.zip", autoBackup.GetName(), time.Now().Unix())
outputPath = filepath.Join(autoBackup.StoragePath, filename)
and for custom directory backups:
filename := fmt.Sprintf("custom_dir_%s_%d.zip", autoBackup.GetName(), time.Now().Unix())
outputPath = filepath.Join(autoBackup.StoragePath, filename)
The API validation rules require name, backup_type, storage_type, storage_path, and cron_expression, but do not reject /, \, or .. in name. ValidateAutoBackupConfig validates backup_path and storage_path, but it does not validate the final outputPath after appending the generated filename.
Relevant paths:
model/auto_backup.goapi/backup/auto_backup.gointernal/backup/auto_backup.gointernal/backup/utils.go
Proof of Concept
The following local-only reproducer mirrors the relevant code path without contacting any external system:
name := "task/../../../escaped"
filename := fmt.Sprintf("custom_dir_%s_%d.zip", getName(name), int64(1715555555))
outputPath := filepath.Join(storageDir, filename)
Setup:
- Create a temporary
granteddirectory. - Set
sourceDirandstorageDirunder that granted directory. - Treat only
grantedas the allowed path boundary. - Use the auto-backup name
task/../../../escaped. - Create the custom-directory backup using the same filename pattern and zip creation behavior.
Observed output:
granted_root=/Users/jagadeshachanta/.cache/tmp/nginx-ui-autobackup-poc-1538710430/granted
validated_storage_path=/Users/jagadeshachanta/.cache/tmp/nginx-ui-autobackup-poc-1538710430/granted/storage
auto_backup_name="task/../../../escaped"
constructed_filename="custom_dir_task/../../../escaped_1715555555.zip"
created_file=/Users/jagadeshachanta/.cache/tmp/nginx-ui-autobackup-poc-1538710430/escaped_1715555555.zip
escaped_validated_storage_path=true
created_file_exists=true
The configured storage path is inside the granted directory, but the created backup file is outside both the storage directory and the granted directory.
A…
- Record
GHSA-jrq7-xrjx-pcfw- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
NVD
6.3
Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.3, Nginx UI validates an automatic backup's storage_path, but AutoBackup.GetName returns a user-controlled name without rejecting path separators or parent-directory components, and downstream filename formatting embeds that result in the final archive filename. An authenticated user who can create or modify an automatic backup can cause filepath.Join to resolve the generated archive path outside the validated storage directory, allowing backup archives to be written with the Nginx UI process privileges. For encrypted configuration backups, the adjacent encryption key file can also be written outside the validated directory. This issue is fixed in version 2.4.3.
- Record
CVE-2026-84320- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
OSV
6.3
Nginx UI: Auto backup name allows path traversal outside validated storage path
Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.3, Nginx UI validates an automatic backup's storage_path, but AutoBackup.GetName returns a user-controlled name without rejecting path separators or parent-directory components, and downstream filename formatting embeds that result in the final archive filename. An authenticated user who can create or modify an automatic backup can cause filepath.Join to resolve the generated archive path outside the validated storage directory, allowing backup archives to be written with the Nginx UI process privileges. For encrypted configuration backups, the adjacent encryption key file can also be written outside the validated directory. This issue is fixed in version 2.4.3.
- Record
CVE-2026-84320- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVGHSA-jrq7-xrjx-pcfw
6.3
Nginx UI: Auto backup name allows path traversal outside validated storage path
Summary
Nginx UI validates backup_path and storage_path against the administrator-defined backup.GrantedAccessPath boundary, but the final auto-backup output filename is built from the user-controlled auto-backup name without stripping path separators or .. components.
An authenticated user who can create or modify an auto-backup task can set a name such as task/../../../escaped. The configured storage_path still passes validation because it is inside GrantedAccessPath, but the generated backup path escapes that storage directory when filepath.Join(storage_path, filename) resolves the embedded traversal sequence.
This bypasses the documented backup path boundary and allows backup archives, and for encrypted configuration backups the adjacent .key file, to be written outside the intended storage directory with the Nginx UI process privileges.
Affected Versions
- Current
devbranch commit checked:4948fba8744e82c3d7003f68ee164e9f49421066 - Latest release checked:
v2.3.10, published 2026-04-28 - The vulnerable filename construction is present in both current
devandv2.3.10.
Security Boundary
The project documentation describes backup.GrantedAccessPath as the critical security boundary for backup operations. It says the setting:
- restricts backup operations to explicitly authorized directories,
- prevents unauthorized access to sensitive system directories,
- enforces administrator-defined boundaries,
- normalizes paths to prevent traversal attempts.
That boundary is enforced for the configured storage_path, but not for the final path after the backup name is appended.
Root Cause
model.AutoBackup.GetName() only trims whitespace and replaces spaces:
func (a *AutoBackup) GetName() string {
return strings.ReplaceAll(strings.TrimSpace(a.Name), " ", "_")
}
The result is then embedded directly into filenames:
filename := fmt.Sprintf("%s_%d.zip", autoBackup.GetName(), time.Now().Unix())
outputPath = filepath.Join(autoBackup.StoragePath, filename)
and for custom directory backups:
filename := fmt.Sprintf("custom_dir_%s_%d.zip", autoBackup.GetName(), time.Now().Unix())
outputPath = filepath.Join(autoBackup.StoragePath, filename)
The API validation rules require name, backup_type, storage_type, storage_path, and cron_expression, but do not reject /, \, or .. in name. ValidateAutoBackupConfig validates backup_path and storage_path, but it does not validate the final outputPath after appending the generated filename.
Relevant paths:
model/auto_backup.goapi/backup/auto_backup.gointernal/backup/auto_backup.gointernal/backup/utils.go
Proof of Concept
The following local-only reproducer mirrors the relevant code path without contacting any external system:
name := "task/../../../escaped"
filename := fmt.Sprintf("custom_dir_%s_%d.zip", getName(name), int64(1715555555))
outputPath := filepath.Join(storageDir, filename)
Setup:
- Create a temporary
granteddirectory. - Set
sourceDirandstorageDirunder that granted directory. - Treat only
grantedas the allowed path boundary. - Use the auto-backup name
task/../../../escaped. - Create the custom-directory backup using the same filename pattern and zip creation behavior.
Observed output:
granted_root=/Users/jagadeshachanta/.cache/tmp/nginx-ui-autobackup-poc-1538710430/granted
validated_storage_path=/Users/jagadeshachanta/.cache/tmp/nginx-ui-autobackup-poc-1538710430/granted/storage
auto_backup_name="task/../../../escaped"
constructed_filename="custom_dir_task/../../../escaped_1715555555.zip"
created_file=/Users/jagadeshachanta/.cache/tmp/nginx-ui-autobackup-poc-1538710430/escaped_1715555555.zip
escaped_validated_storage_path=true
created_file_exists=true
The configured storage path is inside the granted directory, but the created backup file is outside both the storage directory and the granted directory.
A…
- Record
GHSA-jrq7-xrjx-pcfw- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVGO-2026-6788 No score
Nginx UI: Auto backup name allows path traversal outside validated storage path in github.com/0xJacky/Nginx-UI
Nginx UI: Auto backup name allows path traversal outside validated storage path in github.com/0xJacky/Nginx-UI
- Record
GO-2026-6788- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/0xJacky/Nginx-UIGo |
before 1.9.10-0.20260715121709-f92218e01054 | 1.9.10-0.20260715121709-f92218e01054 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-84320 is a medium vulnerability (CVSS 6.3) in 0xjacky Nginx-ui, published October 12, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.17%, the 6th percentile. Fixed in github.com/0xJacky/Nginx-UI 1.9.10-0.20260715121709-f92218e01054.
References
github.com/0xJacky/nginx-ui/security/advisories/GHSA-jrq7-xrjx-pcfw
github.com/0xJacky/nginx-ui/commit/f92218e01054491fc1e6684dc6f7facaf8ab41eb
github.com/0xJacky/nginx-ui/releases/tag/v2.4.3
nvd.nist.gov/vuln/detail/CVE-2026-84320
github.com/advisories/GHSA-jrq7-xrjx-pcfw
github.com/CVEProject/cvelistV5/tree/main/cves/2026/84xxx/CVE-2026-84320.json
github.com/0xJacky/nginx-ui
Left out here: the rest of 2 source descriptions. The JSON record has them.