CVE-2026-107811
0xJacky/nginx-ui /api/nodes Leaks Cluster Node Tokens and Allows Cross-Node Impersonation as initUser
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, ordinary authenticated users can access /api/nodes and /api/nodes/:id, whose responses serialize the node token field. The same token is accepted as X-Node-Secret by AuthRequired and maps the request to initUser, allowing the user to impersonate a trusted node against a reachable cluster member. This cross-node authentication bypass can expose sensitive management operations, including configuration synchronization and service restart. This issue is fixed in version 2.5.0.
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
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.8
0xJacky/nginx-ui /api/nodes Leaks Cluster Node Tokens and Allows Cross-Node Impersonation as initUser
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, ordinary authenticated users can access /api/nodes and /api/nodes/:id, whose responses serialize the node token field. The same token is accepted as X-Node-Secret by AuthRequired and maps the request to initUser, allowing the user to impersonate a trusted node against a reachable cluster member. This cross-node authentication bypass can expose sensitive management operations, including configuration synchronization and service restart. This issue is fixed in version 2.5.0.
- Record
CVE-2026-107811- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-200, CWE-862
- Updated
- 2026-11-02
EUVDEUVD-2026-95895
8.8
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, ordinary authenticated users can access /api/nodes and /api/nodes/:id, whose responses serialize the node token field. The same token is accepted as X-Node-Secret by AuthRequired and maps the request to initUser, allowing the user to impersonate a trusted node against a reachable cluster member. This cross-node authentication bypass can expose sensitive management operations, including configuration synchronization and service restart. This issue is fixed in version 2.5.0.
- Record
EUVD-2026-95895- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-32gc-wf3m-78w9
8.8
0xJacky/nginx-ui /api/nodes Leaks Cluster Node Tokens and Allows Cross-Node Impersonation as initUser
Summary 0xJacky/nginx-ui contains a high-severity trust-boundary failure between ordinary users and cluster node credentials. The source code shows that cluster node list and detail endpoints are reachable by ordinary authenticated users and return node objects containing the token field.
That same token is also used as the X-Node-Secret shared credential for node-to-node authentication. When the middleware receives a correct node secret, it upgrades the request to initUser and bypasses the normal user-authentication path. As a result, any low-privileged authenticated user can first read a node token from /api/nodes and then impersonate a trusted node against a remote node's management API, achieving cross-node administrative authentication bypass.
Details The root cause is a combination of sensitive credential exposure and improper trust elevation for node-to-node authentication. First, router/routers.go:87-105 mounts cluster.InitRouter(g) inside the shared /api authenticated route group, so any successfully authenticated user can access node list and detail endpoints.
Next, api/cluster/node.go:19-48 implements GetNode and GetNodeList by directly returning analytic.GetNode(node). Meanwhile, model/node.go:8-13 defines Token with the JSON tag json:"token", meaning the node secret is serialized into API responses. The surrounding code path does not redact that field. Therefore, a low-privileged user can call /api/nodes or /api/nodes/:id and retrieve both the target node URL and the token value used for trusted node authentication.
The second half of the exploit chain is in internal/middleware/middleware.go:73-103. The middleware reads a node secret from the X-Node-Secret header or node_secret query parameter. If that supplied value matches settings.NodeSettings.Secret, the request is immediately associated with user.GetInitUser(c), stored in the context as user, and allowed to continue. In other words, possession of the node secret is treated as sufficient to become initUser and bypass the normal JWT-based user-authentication flow.
This makes the disclosed token directly reusable for privilege escalation. A low-privileged user logs in to the primary instance, retrieves the cluster node token through /api/nodes, then sends a request to the remote node with X-Node-Secret set to the leaked token. Because the remote node upgrades the request to initUser, the attacker can invoke sensitive management handlers. The verified evidence identifies api/system/router.go and api/system/restart.go as examples of reachable high-risk operations, including POST /api/system/restart.
Core vulnerable code path:
go // router/routers.go:87-105 g := root.Group("/", middleware.AuthRequired(), middleware.Proxy()) { debug.InitRouter(g) user.InitUserRouter(g) analytic.InitRouter(g) user.InitManageUserRouter(g) nginx.InitRouter(g) sites.InitRouter(g) streams.InitRouter(g) config.InitRouter(g) template.InitRouter(g) certificate.InitCertificateRouter(g) certificate.InitDNSCredentialRouter(g) certificate.InitAcmeUserRouter(g) dnsapi.InitRouter(g) system.InitPrivateRouter(g) settings.InitRouter(g) llm.InitRouter(g) cluster.InitRouter(g) notification.InitRouter(g) external_notify.InitRouter(g) backup.InitAutoBackupRouter(g) nginxLog.InitRouter(g) upstream.InitHTTPRouter(g) g.GET("/geolite/status", geolite.GetStatus) } This route block shows that cluster endpoints are mounted in the shared authenticated route group. Any user with a valid JWT can reach cluster management APIs; there is no administrator-only authorization gate here.
go // api/cluster/node.go:19-48 func GetNode(c *gin.Context) { id := cast.ToUint64(c.Param("id"))
nodeQuery := query.Node
node, err := nodeQuery.FirstByID(id)
if err != nil {
cosy.ErrHandler(c, err)
return
}
c.JSON(http.StatusOK, analytic.GetNode(node))
}
func GetNodeList(c *gin.Context) { core := cosy.Coremodel.Node. SetFussy("name")
// fix for sqlite
if c.Query("enabled") != ""…
- Record
GHSA-32gc-wf3m-78w9- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-200, CWE-862
- Updated
- 2026-11-02
NVD
8.8
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, ordinary authenticated users can access /api/nodes and /api/nodes/:id, whose responses serialize the node token field. The same token is accepted as X-Node-Secret by AuthRequired and maps the request to initUser, allowing the user to impersonate a trusted node against a reachable cluster member. This cross-node authentication bypass can expose sensitive management operations, including configuration synchronization and service restart. This issue is fixed in version 2.5.0.
- Record
CVE-2026-107811- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-200, CWE-862
- Updated
- 2026-11-02
OSV
8.8
0xJacky/nginx-ui /api/nodes Leaks Cluster Node Tokens and Allows Cross-Node Impersonation as initUser
Nginx UI is a web user interface for the Nginx web server. From 2.0.0 until 2.5.0, ordinary authenticated users can access /api/nodes and /api/nodes/:id, whose responses serialize the node token field. The same token is accepted as X-Node-Secret by AuthRequired and maps the request to initUser, allowing the user to impersonate a trusted node against a reachable cluster member. This cross-node authentication bypass can expose sensitive management operations, including configuration synchronization and service restart. This issue is fixed in version 2.5.0.
- Record
CVE-2026-107811- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-200, CWE-862
- Updated
- 2026-11-02
OSVGHSA-32gc-wf3m-78w9
8.8
0xJacky/nginx-ui /api/nodes Leaks Cluster Node Tokens and Allows Cross-Node Impersonation as initUser
Summary 0xJacky/nginx-ui contains a high-severity trust-boundary failure between ordinary users and cluster node credentials. The source code shows that cluster node list and detail endpoints are reachable by ordinary authenticated users and return node objects containing the token field.
That same token is also used as the X-Node-Secret shared credential for node-to-node authentication. When the middleware receives a correct node secret, it upgrades the request to initUser and bypasses the normal user-authentication path. As a result, any low-privileged authenticated user can first read a node token from /api/nodes and then impersonate a trusted node against a remote node's management API, achieving cross-node administrative authentication bypass.
Details The root cause is a combination of sensitive credential exposure and improper trust elevation for node-to-node authentication. First, router/routers.go:87-105 mounts cluster.InitRouter(g) inside the shared /api authenticated route group, so any successfully authenticated user can access node list and detail endpoints.
Next, api/cluster/node.go:19-48 implements GetNode and GetNodeList by directly returning analytic.GetNode(node). Meanwhile, model/node.go:8-13 defines Token with the JSON tag json:"token", meaning the node secret is serialized into API responses. The surrounding code path does not redact that field. Therefore, a low-privileged user can call /api/nodes or /api/nodes/:id and retrieve both the target node URL and the token value used for trusted node authentication.
The second half of the exploit chain is in internal/middleware/middleware.go:73-103. The middleware reads a node secret from the X-Node-Secret header or node_secret query parameter. If that supplied value matches settings.NodeSettings.Secret, the request is immediately associated with user.GetInitUser(c), stored in the context as user, and allowed to continue. In other words, possession of the node secret is treated as sufficient to become initUser and bypass the normal JWT-based user-authentication flow.
This makes the disclosed token directly reusable for privilege escalation. A low-privileged user logs in to the primary instance, retrieves the cluster node token through /api/nodes, then sends a request to the remote node with X-Node-Secret set to the leaked token. Because the remote node upgrades the request to initUser, the attacker can invoke sensitive management handlers. The verified evidence identifies api/system/router.go and api/system/restart.go as examples of reachable high-risk operations, including POST /api/system/restart.
Core vulnerable code path:
go // router/routers.go:87-105 g := root.Group("/", middleware.AuthRequired(), middleware.Proxy()) { debug.InitRouter(g) user.InitUserRouter(g) analytic.InitRouter(g) user.InitManageUserRouter(g) nginx.InitRouter(g) sites.InitRouter(g) streams.InitRouter(g) config.InitRouter(g) template.InitRouter(g) certificate.InitCertificateRouter(g) certificate.InitDNSCredentialRouter(g) certificate.InitAcmeUserRouter(g) dnsapi.InitRouter(g) system.InitPrivateRouter(g) settings.InitRouter(g) llm.InitRouter(g) cluster.InitRouter(g) notification.InitRouter(g) external_notify.InitRouter(g) backup.InitAutoBackupRouter(g) nginxLog.InitRouter(g) upstream.InitHTTPRouter(g) g.GET("/geolite/status", geolite.GetStatus) } This route block shows that cluster endpoints are mounted in the shared authenticated route group. Any user with a valid JWT can reach cluster management APIs; there is no administrator-only authorization gate here.
go // api/cluster/node.go:19-48 func GetNode(c *gin.Context) { id := cast.ToUint64(c.Param("id"))
nodeQuery := query.Node
node, err := nodeQuery.FirstByID(id)
if err != nil {
cosy.ErrHandler(c, err)
return
}
c.JSON(http.StatusOK, analytic.GetNode(node))
}
func GetNodeList(c *gin.Context) { core := cosy.Coremodel.Node. SetFussy("name")
// fix for sqlite
if c.Query("enabled") != ""…
- Record
GHSA-32gc-wf3m-78w9- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-200, CWE-862
- Updated
- 2026-11-02
OSVGO-2026-6702 No score
0xJacky/nginx-ui /api/nodes Leaks Cluster Node Tokens and Allows Cross-Node Impersonation as initUser in github.com/0xJacky/Nginx-UI
0xJacky/nginx-ui /api/nodes Leaks Cluster Node Tokens and Allows Cross-Node Impersonation as initUser in github.com/0xJacky/Nginx-UI
- Record
GO-2026-6702- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/0xJacky/Nginx-UIGo |
1.9.10-0.20250517140552-daee3ac7ade1 up to 1.9.10-0.20260728091109-0ecbd106c37b | 1.9.10-0.20260728091109-0ecbd106c37b |
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-107811 is a high vulnerability (CVSS 8.8) in 0xjacky Nginx-ui, published October 9, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.43%, the 37th percentile. Fixed in github.com/0xJacky/Nginx-UI 1.9.10-0.20260728091109-0ecbd106c37b.
References
github.com/0xJacky/nginx-ui/security/advisories/GHSA-32gc-wf3m-78w9
github.com/0xJacky/nginx-ui/commit/0ecbd106c37b5143be14880c9447a66135151512
github.com/0xJacky/nginx-ui/releases/tag/v2.5.0
github.com/advisories/GHSA-32gc-wf3m-78w9
github.com/CVEProject/cvelistV5/tree/main/cves/2026/107xxx/CVE-2026-107811.json
nvd.nist.gov/vuln/detail/CVE-2026-107811
github.com/0xJacky/nginx-ui
Left out here: the rest of 2 source descriptions. The JSON record has them.