CVE-2026-107809

CVE-2026-107809 is a high-severity cross-site request forgery (CSRF) vulnerability in github.com/0xJacky/Nginx-UI (go), affecting versions >= 1.9.10-0.20250517140552-daee3ac7ade1, < 1.9.10-0.20260728074433-a3999bd78a3b. It is fixed in 1.9.10-0.20260728074433-a3999bd78a3b.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Nginx-UI AuthRequired token cookie fallback enables CSRF against management APIs

Nginx-UI v2.4.3 stores the API JWT in a browser cookie named token and the AuthRequired middleware accepts that cookie as an authentication source. Because management endpoints are protected by AuthRequired and do not enforce a universal CSRF token or Origin/Referer check, a remote attacker can induce a logged-in administrator to submit cross-site state-changing requests. The attacker does not need to read the cross-origin response; the browser-sent cookie is enough to authenticate the request.

Details

The root cause is a trust-boundary failure between browser-managed cookies and API bearer-token authentication. In app/src/pinia/moudule/user.ts:25-35, the front end writes the JWT to a token cookie when the token changes. In internal/middleware/middleware.go:16-36, getToken first checks the Authorization header and token query parameter, then falls back to c.Cookie("token"). That fallback causes browser-initiated cross-site requests to carry a valid API credential automatically. The route group in router/routers.go:87-110 applies middleware.AuthRequired() to many management modules, including config.InitRouter, nginx.InitRouter, settings.InitRouter, and backup-related handlers. For accounts without OTP/Passkey, RequireSecureSession does not provide a universal second factor for all state-changing operations. A representative sink is api/config/add.go:68-78, where an authenticated request writes Nginx configuration with os.WriteFile and then calls nginx.Control(nginx.Reload). CORS does not mitigate this issue because preventing cross-origin response reads does not prevent cross-site form or no-cors requests from being sent with cookies.

Core vulnerable code path:

// app/src/pinia/moudule/user.ts:25-35
watch(token, v => {
    if (v) {
      cookies.set('token', v, getCookieOptions(86400))
      if (!shortToken.value) {
        void fetchShortToken()
      }
    }
    else {
      cookies.remove('token', { path: '/' })
      shortToken.value = ''
    }
  })

The front end stores the authentication token in a token cookie. The cookie is created client-side and is not shown here as HttpOnly; it becomes the credential that the back end later accepts through cookie fallback.

// internal/middleware/middleware.go:16-36
// getToken from header, cookie or query
func getToken(c *gin.Context) (token string) {
	if token = c.GetHeader("Authorization"); token != "" {
		return
	}

	if token = c.Query("token"); token != "" {
		if len(token) > 16 {
			// Long token (base64 encoded JWT)
			tokenBytes, _ := base64.StdEncoding.DecodeString(token)
			return string(tokenBytes)
		}
		// Short token (16 characters)
		return token
	}

	if token, _ = c.Cookie("token"); token != "" {
		return token
	}

	return ""
}

getToken accepts the token cookie as an authentication credential after checking the header and query parameter. That behavior lets a browser-sent cookie authenticate state-changing API requests triggered from another origin.

// router/routers.go:87-110
// Authorization required and not websocket request
		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)

Many management modules, including Nginx, configuration, settings, backup, and user management, are placed behind AuthRequired. The cookie fallback therefore protects high-impact state-changing routes, not only read-only endpoints.

// api/config/add.go:68-78
err = os.WriteFile(path, []byte(content), 0644)
	if err != nil {
		cosy.ErrHandler(c, err)
		return
	}

	res := nginx.Control(nginx.Reload)
	if res.IsError() {
		res.RespError(c)
		return
	}

This representative sink shows why the CSRF is high impact: once authenticated through the cookie fallback, a request can write Nginx configuration content and trigger a reload.

POC

Prerequisites: an administrator is logged in to Nginx-UI and has a browser token cookie; the administrator account has not enabled OTP/Passkey, or the chosen target endpoint does not require secure-session proof; the attacker knows the Nginx-UI management URL and can induce the administrator to visit an attacker-controlled page. Reproduction: (1) Host an attacker page at GET /csrf.html that automatically submits a cross-site request to the victim instance. (2) The page submits POST /api/configs with configuration fields such as base_dir, name, content, overwrite, and sync_node_ids; the attacker does not need to read the response. (3) When the administrator visits the page, the browser attaches the victim site's token cookie. (4) Expected result: AuthRequired authenticates from the cookie, AddConfig writes the Nginx configuration, and the application attempts an Nginx reload. Testing should use a harmless configuration in an isolated environment.

Impact

An attacker can trigger administrative operations while an administrator is logged in, including Nginx configuration creation or modification, reload/restart operations, settings changes, and backup-related actions depending on endpoint protections. Direct impacts include traffic redirection, reverse proxy tampering, denial of service, and sensitive configuration changes. In deployments with permissive Nginx modules or dangerous configuration capabilities, configuration tampering may lead to further server-side impact or internal network abuse.

A victim's authenticated browser session is used to submit forged requests to an application that cannot distinguish them from legitimate ones. Typical impact: state-changing actions performed as the victim without their consent.

CVE-2026-107809 has a CVSS score of 8.8 (High). The vector is network-reachable, no privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.9.10-0.20260728074433-a3999bd78a3b); upgrading removes the vulnerable code path.

Affected versions

github.com/0xJacky/Nginx-UI (>= 1.9.10-0.20250517140552-daee3ac7ade1, < 1.9.10-0.20260728074433-a3999bd78a3b)

Security releases

github.com/0xJacky/Nginx-UI → 1.9.10-0.20260728074433-a3999bd78a3b (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade github.com/0xJacky/Nginx-UI to 1.9.10-0.20260728074433-a3999bd78a3b or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-107809? CVE-2026-107809 is a high-severity cross-site request forgery (CSRF) vulnerability in github.com/0xJacky/Nginx-UI (go), affecting versions >= 1.9.10-0.20250517140552-daee3ac7ade1, < 1.9.10-0.20260728074433-a3999bd78a3b. It is fixed in 1.9.10-0.20260728074433-a3999bd78a3b. A victim's authenticated browser session is used to submit forged requests to an application that cannot distinguish them from legitimate ones.
  2. How severe is CVE-2026-107809? CVE-2026-107809 has a CVSS score of 8.8 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of github.com/0xJacky/Nginx-UI are affected by CVE-2026-107809? github.com/0xJacky/Nginx-UI (go) versions >= 1.9.10-0.20250517140552-daee3ac7ade1, < 1.9.10-0.20260728074433-a3999bd78a3b is affected.
  4. Is there a fix for CVE-2026-107809? Yes. CVE-2026-107809 is fixed in 1.9.10-0.20260728074433-a3999bd78a3b. Upgrade to this version or later.
  5. Is CVE-2026-107809 exploitable, and should I be worried? Whether CVE-2026-107809 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-107809 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-107809? Upgrade github.com/0xJacky/Nginx-UI to 1.9.10-0.20260728074433-a3999bd78a3b or later.

Other vulnerabilities in github.com/0xJacky/Nginx-UI

Stop the waste.
Protect your environment with Kodem.