Every CVE Search/ Get API key

CVE-2026-84315

Nginx UI OTP secure-session step-up is missing on sensitive mutation routes

8.3 HighFix available

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, Nginx UI does not apply RequireSecureSession to multiple authenticated mutation routes even though OTP-enabled users are expected to present a fresh X-Secure-Session-ID for sensitive actions. A stolen authenticated session can therefore create or alter automatic backups, DNS credentials and records, certificates and ACME users, Nginx control settings, and site or stream automation without completing the OTP or passkey step-up. This issue is fixed in version 2.4.1.

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
High
Availability
High

Exploit likelihood

0.34%Up 0.1 points since Oct 13, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.3

Nginx UI OTP secure-session step-up is missing on sensitive mutation routes

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, Nginx UI does not apply RequireSecureSession to multiple authenticated mutation routes even though OTP-enabled users are expected to present a fresh X-Secure-Session-ID for sensitive actions. A stolen authenticated session can therefore create or alter automatic backups, DNS credentials and records, certificates and ACME users, Nginx control settings, and site or stream automation without completing the OTP or passkey step-up. This issue is fixed in version 2.4.1.

Record
CVE-2026-84315
CVSS 3.1
8.3 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H
Weakness
CWE-862
Updated
2026-11-02
EUVDEUVD-2026-97830 8.3

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, Nginx UI does not apply RequireSecureSession to multiple authenticated mutation routes even though OTP-enabled users are expected to present a fresh X-Secure-Session-ID for sensitive actions. A stolen authenticated session can therefore create or alter automatic backups, DNS credentials and records, certificates and ACME users, Nginx control settings, and site or stream automation without completing the OTP or passkey step-up. This issue is fixed in version 2.4.1.

Record
EUVD-2026-97830
CVSS 3.1
8.3 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-5v7c-xpfp-p65m 8.3

Nginx UI OTP secure-session step-up is missing on sensitive mutation routes

Reporter: Jagadesh Achanta

Target: 0xJacky/nginx-ui

Affected version / commit tested:

  • App version: 2.3.10
  • Commit: 4948fba8744e82c3d7003f68ee164e9f49421066
  • Disclosure channel: GitHub Private Vulnerability Reporting
  • Credential reference: cred:github-jagstack-gh-cli

AI assistance disclosure

This report was prepared by Jagadesh Achanta with assistance from OpenAI/Codex for public source review, local evidence collection, and report drafting.

Summary

Nginx UI has a short-lived OTP/passkey "secure session" step-up boundary for users with 2FA enabled. RequireSecureSession() rejects an OTP-enabled user's request unless the request includes a valid X-Secure-Session-ID issued after a fresh OTP/passkey verification.

The project already applies this step-up middleware to sensitive operations such as:

  • Nginx config create/edit/rename/delete;
  • site save/delete/enable/disable/rename/duplicate;
  • stream save/delete/enable/disable/rename/duplicate;
  • settings save and protected secret reads;
  • backup restore.

However, several similarly sensitive authenticated mutation routes remain outside RequireSecureSession(). An attacker who obtains an authenticated JWT/session for a 2FA-enabled user, but does not have the victim's fresh OTP/passkey secure-session token, can still perform those operations.

The affected route groups include:

  • automatic backup create/modify/delete/restore/test-S3 operations;
  • DNS credential create/edit/delete operations;
  • certificate and ACME user create/modify/delete/register operations;
  • DNS domain, record, and DDNS create/update/delete operations;
  • Nginx reload/restart, stub-status toggle, performance-setting update, and module-cache refresh operations;
  • site/stream advanced-mode toggles and batch updates;
  • auto-certificate binding/unbinding for sites;
  • site navigation order and health-check updates.

This report is distinct from my earlier Nginx UI report about auto-backup path traversal. This report is about missing 2FA step-up authorization on sensitive authenticated mutation routes.

Why this is a security boundary

internal/middleware/secure_session.go only requires a secure-session token for users with OTP enabled. For OTP users, it reads X-Secure-Session-ID from the header or query string and aborts with 401 Unauthorized if the secure session is missing or invalid:

if !cUser.EnabledOTP() {
    c.Next()
    return
}
ssid := c.GetHeader("X-Secure-Session-ID")
if ssid == "" {
    ssid = c.Query("X-Secure-Session-ID")
}
if ssid == "" {
    c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
        "message": "Secure Session ID is empty",
    })
    return
}

if user.VerifySecureSessionID(ssid, cUser.ID) {
    c.Next()
    return
}

internal/user/otp.go issues the secure-session ID for only 10 minutes:

func SetSecureSessionID(userId uint64) (sessionId string) {
    sessionId = uuid.NewString()
    cache.Set(secureSessionIDCacheKey(sessionId), userId, 10*time.Minute)
    return
}

The UI/server already rely on this boundary for sensitive actions. For example, api/config/router.go wraps config mutations with RequireSecureSession():

o := r.Group("", middleware.RequireSecureSession())
{
    o.POST("configs", AddConfig)
    o.POST("config", EditConfig)
    o.POST("config_mkdir", Mkdir)
    o.POST("config_rename", Rename)
    o.POST("config_delete", DeleteConfig)
}

api/sites/router.go protects normal site mutations:

o := r.Group("", middleware.RequireSecureSession())
{
    o.POST("sites/:name/rename", RenameSite)
    o.POST("sites/:name/enable", EnableSite)
    o.POST("sites/:name/disable", DisableSite)
    o.POST("sites/:name", SaveSite)
    o.DELETE("sites/:name", DeleteSite)
    o.POST("sites/:name/duplicate", DuplicateSite)
    o.POST("sites/:name/maintenance", EnableMaintenanceSite)
}

api/streams/router.go protects normal stream mutations, and api/settings/router.go protects secret reads/settings saves:…

Record
GHSA-5v7c-xpfp-p65m
CVSS 3.1
8.3 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H
Weakness
CWE-862
Updated
2026-11-02
NVD 8.3

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, Nginx UI does not apply RequireSecureSession to multiple authenticated mutation routes even though OTP-enabled users are expected to present a fresh X-Secure-Session-ID for sensitive actions. A stolen authenticated session can therefore create or alter automatic backups, DNS credentials and records, certificates and ACME users, Nginx control settings, and site or stream automation without completing the OTP or passkey step-up. This issue is fixed in version 2.4.1.

Record
CVE-2026-84315
CVSS 3.1
8.3 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H
Weakness
CWE-862
Updated
2026-11-02
OSV 8.3

Nginx UI OTP secure-session step-up is missing on sensitive mutation routes

Nginx UI is a web user interface for the Nginx web server. Prior to 2.4.1, Nginx UI does not apply RequireSecureSession to multiple authenticated mutation routes even though OTP-enabled users are expected to present a fresh X-Secure-Session-ID for sensitive actions. A stolen authenticated session can therefore create or alter automatic backups, DNS credentials and records, certificates and ACME users, Nginx control settings, and site or stream automation without completing the OTP or passkey step-up. This issue is fixed in version 2.4.1.

Record
CVE-2026-84315
CVSS 3.1
8.3 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H
Weakness
CWE-862
Updated
2026-11-02
OSVGHSA-5v7c-xpfp-p65m 8.3

Nginx UI OTP secure-session step-up is missing on sensitive mutation routes

Reporter: Jagadesh Achanta

Target: 0xJacky/nginx-ui

Affected version / commit tested:

  • App version: 2.3.10
  • Commit: 4948fba8744e82c3d7003f68ee164e9f49421066
  • Disclosure channel: GitHub Private Vulnerability Reporting
  • Credential reference: cred:github-jagstack-gh-cli

AI assistance disclosure

This report was prepared by Jagadesh Achanta with assistance from OpenAI/Codex for public source review, local evidence collection, and report drafting.

Summary

Nginx UI has a short-lived OTP/passkey "secure session" step-up boundary for users with 2FA enabled. RequireSecureSession() rejects an OTP-enabled user's request unless the request includes a valid X-Secure-Session-ID issued after a fresh OTP/passkey verification.

The project already applies this step-up middleware to sensitive operations such as:

  • Nginx config create/edit/rename/delete;
  • site save/delete/enable/disable/rename/duplicate;
  • stream save/delete/enable/disable/rename/duplicate;
  • settings save and protected secret reads;
  • backup restore.

However, several similarly sensitive authenticated mutation routes remain outside RequireSecureSession(). An attacker who obtains an authenticated JWT/session for a 2FA-enabled user, but does not have the victim's fresh OTP/passkey secure-session token, can still perform those operations.

The affected route groups include:

  • automatic backup create/modify/delete/restore/test-S3 operations;
  • DNS credential create/edit/delete operations;
  • certificate and ACME user create/modify/delete/register operations;
  • DNS domain, record, and DDNS create/update/delete operations;
  • Nginx reload/restart, stub-status toggle, performance-setting update, and module-cache refresh operations;
  • site/stream advanced-mode toggles and batch updates;
  • auto-certificate binding/unbinding for sites;
  • site navigation order and health-check updates.

This report is distinct from my earlier Nginx UI report about auto-backup path traversal. This report is about missing 2FA step-up authorization on sensitive authenticated mutation routes.

Why this is a security boundary

internal/middleware/secure_session.go only requires a secure-session token for users with OTP enabled. For OTP users, it reads X-Secure-Session-ID from the header or query string and aborts with 401 Unauthorized if the secure session is missing or invalid:

if !cUser.EnabledOTP() {
    c.Next()
    return
}
ssid := c.GetHeader("X-Secure-Session-ID")
if ssid == "" {
    ssid = c.Query("X-Secure-Session-ID")
}
if ssid == "" {
    c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
        "message": "Secure Session ID is empty",
    })
    return
}

if user.VerifySecureSessionID(ssid, cUser.ID) {
    c.Next()
    return
}

internal/user/otp.go issues the secure-session ID for only 10 minutes:

func SetSecureSessionID(userId uint64) (sessionId string) {
    sessionId = uuid.NewString()
    cache.Set(secureSessionIDCacheKey(sessionId), userId, 10*time.Minute)
    return
}

The UI/server already rely on this boundary for sensitive actions. For example, api/config/router.go wraps config mutations with RequireSecureSession():

o := r.Group("", middleware.RequireSecureSession())
{
    o.POST("configs", AddConfig)
    o.POST("config", EditConfig)
    o.POST("config_mkdir", Mkdir)
    o.POST("config_rename", Rename)
    o.POST("config_delete", DeleteConfig)
}

api/sites/router.go protects normal site mutations:

o := r.Group("", middleware.RequireSecureSession())
{
    o.POST("sites/:name/rename", RenameSite)
    o.POST("sites/:name/enable", EnableSite)
    o.POST("sites/:name/disable", DisableSite)
    o.POST("sites/:name", SaveSite)
    o.DELETE("sites/:name", DeleteSite)
    o.POST("sites/:name/duplicate", DuplicateSite)
    o.POST("sites/:name/maintenance", EnableMaintenanceSite)
}

api/streams/router.go protects normal stream mutations, and api/settings/router.go protects secret reads/settings saves:…

Record
GHSA-5v7c-xpfp-p65m
CVSS 3.1
8.3 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H
Weakness
CWE-862
Updated
2026-11-02
OSVGO-2026-6775 No score

Nginx UI OTP secure-session step-up is missing on sensitive mutation routes in github.com/0xJacky/Nginx-UI

Nginx UI OTP secure-session step-up is missing on sensitive mutation routes in github.com/0xJacky/Nginx-UI

Record
GO-2026-6775
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
github.com/0xJacky/Nginx-UI
Go
before 1.9.10-0.20260703131214-23d1934099b0
1.9.10-0.20260703131214-23d1934099b0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-84315 is a high vulnerability (CVSS 8.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.34%, the 27th percentile. Fixed in github.com/0xJacky/Nginx-UI 1.9.10-0.20260703131214-23d1934099b0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open