CVE-2026-84312: Nginx-UI: Casdoor SSO login CSRF forces victim into attacker session

GHSA-44xr-mrhh-qm78HIGHPoC AVAILABLECISA: TRACK*
Published October 15, 2026
CISO Take

Nginx-UI's Casdoor SSO callback uses a constant, hard-coded OAuth state value and never validates it against a per-session cookie, so an attacker can make a victim's browser log in as the attacker (login CSRF, CWE-352/CWE-287). The flaw is not AI-specific: Nginx-UI is a web management console for Nginx, and it only touches AI/ML estates if it fronts model gateways, inference APIs or LLM apps. Exploitation needs user interaction (CVSS 7.1) and there is no public exploit, Nuclei template or KEV listing. EPSS is low (0.00175) but sits in the top 93rd percentile, so opportunistic abuse is plausible. If you use Casdoor SSO with Nginx-UI, upgrade to a build containing commit 23d1934 (v2.4.1 release referenced in the advisory) or disable Casdoor login and use the correctly implemented OIDC integration instead. Treat any site, TLS key or proxy configuration entered during a suspect session as potentially disclosed.

Sources:NVDGitHub AdvisoryEPSSATLAS

What is the risk?

Medium-to-high for organizations running Nginx-UI with Casdoor SSO enabled; not affected otherwise. Network-exploitable with low complexity and no privileges, but it requires the victim to load an attacker-controlled page and the attacker must hold a valid Casdoor account. Confidentiality impact is high because victim-entered data (TLS private keys, upstream configs) lands in an attacker-controlled account. Integrity impact is low (attribution confusion). No known in-the-wild exploitation, no public PoC tooling beyond the advisory's description, and not in CISA KEV. AI relevance is indirect: only matters where Nginx-UI manages reverse proxies in front of AI/ML services.

How does the attack unfold?

Initial Access
Attacker obtains a Casdoor authorization code for their own account and lures an Nginx-UI administrator to a malicious page.
AML.T0011.003
Exploitation
The page auto-submits the attacker's code with the constant state value to the callback, which accepts it without state validation.
AML.T0049
Session Fixation
The victim's browser receives a valid session cookie for the attacker's account and is silently logged in as the attacker.
AML.T0012
Impact
The victim uploads TLS keys and proxy configuration into the attacker's account, which the attacker then reads.
AML.T0025

What systems are affected?

PackageEcosystemVulnerable RangePatched
Nginx-UIgo< 1.9.10-0.20260703131214-23d1934099b0No patch
github.com/0xJacky/Nginx-UIgo< 1.9.10-0.20260703131214-23d1934099b01.9.10-0.20260703131214-23d1934099b0

How severe is it?

CVSS 3.1
7.1 / 10
EPSS
0.2%
chance of exploitation in 30 days
Higher than 7% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Trivial
Exploitation Confidence
medium
○CISA SSVC: Public PoC
○Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, VulnCheck KEV, CISA SSVC, EPSS, Metasploit, Exploit-DB, trickest/cve, Nuclei templates, and inthewild.io exploitation reports.

What is the attack surface?

AVACPRUISCIA
AVNetwork
ACLow
PRNone
UIRequired
SUnchanged
CHigh
ILow
ANone

What should I do?

1 step
  1. 1) Upgrade Nginx-UI to a release containing commit 23d1934099b05b2a01589b48129dc3d3159d91c2 (v2.4.1 per the advisory); the affected range is below 1.9.10-0.20260703131214-23d1934099b0 in Go module versioning. 2) Until patched, disable Casdoor SSO and use the OIDC integration, which generates a random state and validates it through a cookie. 3) Restrict the Nginx-UI management interface to VPN or an internal network and avoid exposing it to the internet. 4) Detection: review auth logs for Casdoor callback requests (/api/casdoor_callback) with no preceding authorize request from the same client, logins from unexpected Casdoor identities, and POSTs with text/plain content type to the callback. 5) If a suspect session is identified, rotate TLS keys and any secrets entered during it, and audit configuration changes.

What does CISA's SSVC say?

DecisionTrack*
Exploitationpoc
AutomatableNo
Technical Impactpartial

Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Article 15-Accuracy, robustness and cybersecurity
ISO 42001
A.6.2.6-AI system operation and monitoring
NIST AI RMF
MANAGE 2.3-Procedures to respond to and recover from unknown risks

Frequently Asked Questions

What is CVE-2026-84312?

Nginx-UI's Casdoor SSO callback uses a constant, hard-coded OAuth state value and never validates it against a per-session cookie, so an attacker can make a victim's browser log in as the attacker (login CSRF, CWE-352/CWE-287). The flaw is not AI-specific: Nginx-UI is a web management console for Nginx, and it only touches AI/ML estates if it fronts model gateways, inference APIs or LLM apps. Exploitation needs user interaction (CVSS 7.1) and there is no public exploit, Nuclei template or KEV listing. EPSS is low (0.00175) but sits in the top 93rd percentile, so opportunistic abuse is plausible. If you use Casdoor SSO with Nginx-UI, upgrade to a build containing commit 23d1934 (v2.4.1 release referenced in the advisory) or disable Casdoor login and use the correctly implemented OIDC integration instead. Treat any site, TLS key or proxy configuration entered during a suspect session as potentially disclosed.

Is CVE-2026-84312 actively exploited?

Proof-of-concept exploit code is publicly available for CVE-2026-84312, increasing the risk of exploitation.

How to fix CVE-2026-84312?

1) Upgrade Nginx-UI to a release containing commit 23d1934099b05b2a01589b48129dc3d3159d91c2 (v2.4.1 per the advisory); the affected range is below 1.9.10-0.20260703131214-23d1934099b0 in Go module versioning. 2) Until patched, disable Casdoor SSO and use the OIDC integration, which generates a random state and validates it through a cookie. 3) Restrict the Nginx-UI management interface to VPN or an internal network and avoid exposing it to the internet. 4) Detection: review auth logs for Casdoor callback requests (/api/casdoor_callback) with no preceding authorize request from the same client, logins from unexpected Casdoor identities, and POSTs with text/plain content type to the callback. 5) If a suspect session is identified, rotate TLS keys and any secrets entered during it, and audit configuration changes.

What systems are affected by CVE-2026-84312?

This vulnerability affects the following AI/ML architecture patterns: Reverse proxy / API gateway management for model serving, LLM gateway front ends, Web-based infrastructure administration consoles.

What is the CVSS score for CVE-2026-84312?

CVE-2026-84312 has a CVSS v3.1 base score of 7.1 (HIGH). The EPSS exploitation probability is 0.17%.

What is the AI security impact?

Affected AI Architectures

Reverse proxy / API gateway management for model servingLLM gateway front endsWeb-based infrastructure administration consoles

MITRE ATLAS Techniques

AML.T0011.003Malicious Link
AML.T0012Valid Accounts
AML.T0049Exploit Public-Facing Application

Compliance Controls Affected

EU AI Act: Article 15
ISO 42001: A.6.2.6
NIST AI RMF: MANAGE 2.3

What are the technical details?

Original Advisory

## Summary In the Casdoor SSO flow, the OAuth `state` parameter is hard-coded to `settings.CasdoorSettings.Application` — a value identical for every user and every login. The callback handler accepts whatever `state` the client sends without comparing it to anything stored in the user agent, enabling a login-CSRF: an attacker can force the victim's browser to authenticate as the *attacker*. ## Details `api/user/casdoor.go:92-117` (`GetCasdoorUri`): ```go func GetCasdoorUri(c *gin.Context) { clientId := settings.CasdoorSettings.ClientId redirectUri := settings.CasdoorSettings.RedirectUri state := settings.CasdoorSettings.Application // ← constant ... c.JSON(http.StatusOK, gin.H{ "uri": fmt.Sprintf( "%s/login/oauth/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=%s&scope=read", endpoint, clientId, encodedRedirectUri, state), }) } ``` `api/user/casdoor.go:24-90` (`CasdoorCallback`): ```go type CasdoorLoginUser struct { Code string `json:"code" binding:"required,max=255"` State string `json:"state" binding:"required,max=255"` } func CasdoorCallback(c *gin.Context) { var loginUser CasdoorLoginUser if !cosy.BindAndValid(c, &loginUser) { return } ... // state is NEVER compared to a per-session value token, err := casdoorsdk.GetOAuthToken(loginUser.Code, loginUser.State) ... u, err := user.GetUser(claims.Name) // username from Casdoor's JWT ... userToken, err := user.GenerateJWT(u) // JWT minted for whatever user came back } ``` Compare with the OIDC implementation in `api/user/oidc.go:35-48`, which generates a random state, stores it in an `oidc_state` cookie, and validates it on the callback. Casdoor has no such check. ## Proof of Concept 1. Attacker initiates a Casdoor authorisation flow on their own browser, obtaining an authorisation `code` for *their* Casdoor account. 2. Attacker hosts a page that auto-submits the captured `code` to the victim's nginx-ui: ```html <html><body><form action="https://victim.example/api/casdoor_callback" method="POST" enctype="text/plain" id="x"> <input name='{"code":"<attacker_code>","state":"<App>","junk":"' value='"}'> </form> <script>document.getElementById('x').submit()</script> </body></html> ``` 3. Server exchanges the attacker's `code`, looks up the username from `claims.Name` in the local user table, and mints a JWT for *that* row. The callback also sets the `_nginx_ui_secure_session` cookie via `middleware.EnsureSecureSessionCookie(c)` (`casdoor.go:84`) — meaning the victim is now silently authenticated as the attacker. 4. Victim, believing they are using their own account, configures sites / TLS keys; the attacker reads them. ## Impact Login CSRF — the victim is forced to authenticate as the attacker, leading to data exfiltration of anything the victim subsequently uploads or configures. Particularly dangerous when nginx-ui is used by an organisation where Casdoor maps internal identities — the attacker can attribute their changes to the victim. ## Patches Mirror the OIDC implementation: ```diff + import ( + "crypto/rand" + "crypto/subtle" + "encoding/hex" + ... + ) func GetCasdoorUri(c *gin.Context) { ... - state := settings.CasdoorSettings.Application + b := make([]byte, 16) + if _, err := rand.Read(b); err != nil { + cosy.ErrHandler(c, err); return + } + state := hex.EncodeToString(b) + c.SetSameSite(http.SameSiteLaxMode) + c.SetCookie("casdoor_state", state, 600, "/", "", + cSettings.ServerSettings.EnableHTTPS, true) ... } func CasdoorCallback(c *gin.Context) { + expected, err := c.Cookie("casdoor_state") + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, + gin.H{"message":"missing state cookie"}); return + } var loginUser CasdoorLoginUser if !cosy.BindAndValid(c, &loginUser) { return } + if subtle.ConstantTimeCompare([]byte(expected), []byte(loginUser.State)) != 1 { + c.AbortWithStatusJSON(http.StatusBadRequest, + gin.H{"message":"invalid state"}); return + } ... } ``` ## Workarounds Disable Casdoor SSO until patched. The OIDC integration in `api/user/oidc.go` is correctly implemented and can be used as a substitute. ## References * [`api/user/casdoor.go:92-117`](https://github.com/0xJacky/nginx-ui/blob/dev/api/user/casdoor.go#L92-L117) * [`api/user/casdoor.go:24-90`](https://github.com/0xJacky/nginx-ui/blob/dev/api/user/casdoor.go#L24-L90) * [`api/user/oidc.go:35-48`](https://github.com/0xJacky/nginx-ui/blob/dev/api/user/oidc.go#L35-L48) (correct implementation for comparison) ## Credits Vishal Shukla ([@shukla304](https://github.com/shukla304)) and Sechub.dev AI Agent.

Exploitation Scenario

An attacker with a valid Casdoor account starts the SSO flow and captures their authorization code without completing it. They host a page that auto-submits the code and the known constant state value to the victim organization's Nginx-UI casdoor_callback endpoint, then lure an administrator to open the page via phishing or chat. The administrator's browser is silently logged in as the attacker and receives a session cookie. Believing they are in their own account, the administrator configures a reverse proxy for an internal LLM gateway and uploads its TLS key and backend addresses. The attacker later logs into their own account and reads that configuration and key material.

Weaknesses (CWE)

CWE-287 — Improper Authentication: When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.

  • [Architecture and Design] Use an authentication framework or library such as the OWASP ESAPI Authentication feature.

Source: MITRE CWE corpus.

CVSS Vector

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N

Timeline

Published
October 15, 2026
Last Modified
October 28, 2026
First Seen
October 16, 2026

Related Vulnerabilities