Threat database
36 threats
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| High | 7.1 | EPSS 0.2% | CVE-2026-84312nginx-ui · Improper Authentication High7.1EPSS 0.2%CVE Database V5CVE-2026-84312 CVE-2026-84312 is an improper authentication vulnerability in the Casdoor SSO flow of 0xJacky nginx-ui. The OAuth state parameter is hard-coded and not validated against a per-session value, enabling login CSRF attacks. An attacker can force a victim's browser to authenticate as the attacker, potentially leading to unauthorized access and data exfiltration. The vulnerability affects versions prior to 2.4.1. A patch is available that implements proper state parameter generation and validation similar to the OIDC flow. | CVE Database V5 | ||
| High | 8.1 | EPSS 0.3% | High8.1EPSS 0.3%CVE Database V5CVE-2026-84360 CVE-2026-84360 is an authentication bypass vulnerability in 0xJacky's nginx-ui product that allows OTP-enabled users to bypass the intended secure session requirement for high-impact Nginx configuration changes. The vulnerability arises because the MCP endpoints, which allow configuration mutations, require only ordinary authentication rather than the stricter secure session. This enables an attacker with valid JWT authentication but without a secure session to modify Nginx configuration via the /mcp and /mcp_message endpoints. The issue was verified with a proof-of-concept demonstrating successful configuration changes without step-up authentication. | CVE Database V5 | ||
| High | 8.8 | EPSS 0.4% | CVE-2026-84316nginx-ui · Improper Input Validation High8.8EPSS 0.4%CVE Database V5CVE-2026-84316 CVE-2026-84316 is an improper input validation vulnerability in 0xJacky's nginx-ui that allows authenticated users to bypass directive validation by placing blocked directives after a semicolon on the same line. This bypass affects all guarded write paths that call the validator, enabling injection of dangerous nginx directives such as js_import, load_module, and user root. On deployments with njs or perl modules enabled, this leads to code execution in the nginx worker process, potentially as root. The vulnerability requires authentication via node secret or user JWT and has been demonstrated on version 2.3.11 of the official Docker image. The issue stems from the validator splitting config content by newlines and only inspecting the first token per line, while nginx parses multiple directives separated by semicolons on the same line. | CVE Database V5 | ||
| High | 8.3 | EPSS 0.3% | CVE-2026-84319nginx-ui · Protection Mechanism Failure High8.3EPSS 0.3%CVE Database V5CVE-2026-84319 CVE-2026-84319 is a vulnerability in 0xJacky's nginx-ui that allows a secondary authenticated user to bypass restricted directive validation in the MCP configuration interface. While the HTTP API blocks restricted Nginx directives such as load_module, js_import, and js_content, the MCP interface permits writing and applying equivalent restricted configurations. This enables execution of attacker-controlled NJS scripts within the Nginx worker context, potentially modifying runtime behavior including responses and routing. The vulnerability affects versions prior to 2.4.1. The CVSS score is 8.3 (high severity). | CVE Database V5 | ||
| High | 8.8 | EPSS 0.4% | CVE-2026-84317nginx-ui · Improper Input Validation High8.8EPSS 0.4%CVE Database V5CVE-2026-84317 CVE-2026-84317 is an improper input validation vulnerability in the 0xJacky nginx-ui product. The vulnerability arises because the MCP tool 'nginx_config_add' does not enforce validation on user-supplied nginx configuration content, unlike other config-write paths. This allows an authenticated user to inject dangerous nginx directives such as 'js_*', 'perl_*', 'load_module', and 'user root', potentially leading to nginx code execution with root privileges if the njs/perl modules are available. The issue is due to an incomplete hardening patch that missed adding validation to the 'nginx_config_add' path. A proof of concept demonstrates remote code execution via JavaScript in the nginx worker running as root. The vulnerability affects versions prior to 2.4.1 and has a CVSS 3.1 score of 8.8 (high severity). | CVE Database V5 | ||
| High | 8.8 | EPSS 0.4% | CVE-2026-84313nginx-ui · Improper Authentication High8.8EPSS 0.4%CVE Database V5CVE-2026-84313 0xJacky nginx-ui versions prior to 2.4.1 contain an improper authentication vulnerability (CWE-287) in the two-factor authentication enrollment endpoints. The endpoints for enrolling TOTP and WebAuthn passkeys require only a valid JWT and are not protected by a secure session middleware, allowing an attacker with a stolen JWT to bind their own second factor to a victim's account without re-authentication. This enables persistent account takeover that survives password resets and locks out legitimate users. | CVE Database V5 | ||
| Medium | 5.4 | EPSS 0.2% | CVE-2026-84321nginx-ui · Insufficient Session Expiration Medium5.4EPSS 0.2%CVE Database V5CVE-2026-84321 CVE-2026-84321 is a medium severity vulnerability in 0xJacky's nginx-ui prior to version 2.4.1 involving insufficient session expiration. Standalone short tokens used for WebSocket and explicit-token authentication remain valid in cache even after administrative revocation. If the associated user account is re-enabled before the cache entry expires, the stale short token can be reused to authenticate successfully. | CVE Database V5 | ||
| High | 8.7 | EPSS 0.3% | CVE-2026-84314nginx-ui · Improper Authorization High8.7EPSS 0.3%CVE Database V5CVE-2026-84314 CVE-2026-84314 is an improper authorization vulnerability in 0xJacky's nginx-ui that allows any authenticated user to change any other user's password without requiring two-factor authentication (2FA). The vulnerable endpoint POST /api/users/:id lacks the RequireSecureSession middleware, unlike other sensitive operations that enforce 2FA. This flaw enables an attacker to take over the initial admin account by changing its password, effectively locking out the legitimate admin user. | CVE Database V5 | ||
| Medium | 6.3 | EPSS 0.2% | CVE-2026-84320nginx-ui · Path Traversal Medium6.3EPSS 0.2%CVE Database V5CVE-2026-84320 CVE-2026-84320 is a path traversal vulnerability in 0xJacky's nginx-ui affecting versions prior to 2.4.3. The issue arises because the auto-backup filename is constructed from a user-controlled name without sanitizing path separators or '..' components, allowing an authenticated user to escape the intended backup storage directory. This bypasses the administrator-defined backup path boundary, potentially enabling backup archives and sensitive encrypted key files to be written outside authorized directories with the privileges of the nginx-ui process. | CVE Database V5 | ||
| High | 8.8 | EPSS 0.6% | CVE-2026-84318nginx-ui · Protection Mechanism Failure High8.8EPSS 0.6%CVE Database V5CVE-2026-84318 CVE-2026-84318 is a vulnerability in 0xJacky's nginx-ui where the MCP tool 'nginx_config_add' writes nginx configuration files without validating them, unlike the REST API which blocks dangerous directives. This allows an authenticated attacker to bypass security checks and write config files with blocked directives such as 'perl' or 'user root', leading to remote code execution on servers with certain nginx modules loaded. The vulnerability affects versions from 2.0.0-rc.6 up to but not including 2.4.1. | CVE Database V5 | ||
| High | 8.3 | EPSS 0.3% | CVE-2026-84315nginx-ui · Missing Authorization High8.3EPSS 0.3%CVE Database V5CVE-2026-84315 CVE-2026-84315 is a missing authorization vulnerability in 0xJacky's nginx-ui version prior to 2.4.1. The application uses a short-lived OTP/passkey "secure session" token to enforce step-up authorization for sensitive operations for users with 2FA enabled. However, several sensitive authenticated mutation routes are not protected by this step-up middleware, allowing an attacker with a valid authenticated JWT/session but without a fresh OTP secure-session token to perform unauthorized sensitive actions. | CVE Database V5 | ||
| High | 8.8 | EPSS 0.3% | CVE-2026-107813nginx-ui · Missing Authorization High8.8EPSS 0.3%CVE Database V5CVE-2026-107813 ## Summary Incomplete fix of GHSA-5v7c-xpfp-p65m: the secure-session (OTP step-up) requirement added to the nginx, cert, dns, backup, site, and stream mutation routers was not applied to the parallel api/cluster router, so cluster node management and cluster-wide nginx reload/restart run with only a JWT and no step-up. An authenticated user whose JWT is stolen or persisted, but who does not hold a fresh secure-session, can perform cluster node CRUD (including reading and rewriting a node token secret) and trigger cluster-wide nginx reload/restart. Confirmed at HEAD 2cb7ee9102c9d87274de2fa104db804841d140a0. ## The defect GHSA-5v7c-xpfp-p65m required a fresh secure session (an OTP step-up beyond the JWT) for sensitive mutation routes. The fix wrapped the nginx, cert, dns, backup, site, and stream mutation handlers in middleware.RequireSecureSession() and added reload/restart to the MCP sensitive-tool list. It did not touch the physically separate api/cluster package, whose router registers the same class of sensitive operations on the bare authenticated group. The fixed sibling, api/nginx/router.go: ```go o := r.Group("", middleware.RequireSecureSession()) // line 28 { o.POST("nginx/reload", Reload) // line 30 o.POST("nginx/restart", Restart) // line 31 } ``` The missed router, api/cluster/router.go, registers every sensitive operation directly on r with no RequireSecureSession wrapper: ```go nodeGroup := r.Group("nodes") // line 9, no step-up { nodeGroup.POST("", AddNode) // line 12 nodeGroup.POST("/:id", EditNode) // line 13 nodeGroup.DELETE("/:id", DeleteNode) // line 14 } r.POST("nodes/reload_nginx", ReloadNginx) // line 17 r.POST("nodes/restart_nginx", RestartNginx) // line 18 r.POST("namespaces", AddNamespace) // line 22 r.POST("namespaces/:id", ModifyNamespace) // line 23 r.DELETE("namespaces/:id", DeleteNamespace) // line 24 ``` Both routers mount on the same group in router/routers.go: `g := root.Group("/", middleware.AuthRequired(), middleware.Proxy())` (line 87); nginx.InitRouter(g) creates its own RequireSecureSession subgroup, cluster.InitRouter(g) does not. So the cluster routes inherit only AuthRequired and Proxy, exactly the pre-fix posture the advisory closed for the nginx routes. AuthRequired has no role gate, so any authenticated user reaches them. ## Attacker model and impact An authenticated, OTP-enabled user who does not present a fresh X-Secure-Session-ID (the parent advisory's model: a stolen or persisted JWT used without the step-up). Such a user can: add/edit/delete cluster nodes (AddNode/EditNode store an AES-serialized node token, the secret used to control a remote node, so this reads back and rewrites a cross-node credential); trigger nodes/reload_nginx and nodes/restart_nginx across the cluster (the exact reload/restart action class the fix protected on the single-node path); and add/modify/delete/reorder namespaces. Proof of concept: with a valid JWT but no fresh secure session, call POST /api/nodes (AddNode) or POST /api/nodes/reload_nginx. The nginx equivalent POST /api/nginx/reload returns the secure-session challenge; the cluster route succeeds. ## Verification Source-verified at HEAD: the nginx router wraps reload/restart in RequireSecureSession, the cluster router registers node/namespace/reload/restart directly on the group with no such wrapper, and both mount on the AuthRequired+Proxy-only group. I did not stand up a live nginx-ui. ## Suggested fix Wrap the cluster router's mutation handlers (node CRUD, nodes/reload_nginx, nodes/restart_nginx, namespace CRUD) in middleware.RequireSecureSession(), mirroring api/nginx/router.go. Secondary lower-confidence items worth checking in the same pass: the system/restart handler, the core-upgrade websocket, and the upstream socket PUT also appear to run without the step-up (I did not fully trace these). | CVE Database V5 | ||
| High | 7.5 | EPSS 0.2% | CVE-2026-107812nginx-ui · Download of Code Without Integrity Check High7.5EPSS 0.2%CVE Database V5CVE-2026-107812 nginx-ui versions 2.0.0 up to but not including 2.5.0 have a vulnerability in their self-upgrade mechanism where the binary and its checksum are downloaded from the same source without cryptographic signature verification. This allows an attacker controlling the download source or performing a man-in-the-middle attack on an HTTP proxy to substitute a malicious binary and matching digest, resulting in root code execution upon upgrade. The upgrade process replaces the running executable and restarts it as root. The vulnerability arises because integrity is only checked by comparing the binary's digest to a digest file fetched from the same origin, and the github_proxy setting accepts HTTP URLs, enabling cleartext interception. No official patch or fix is indicated in the provided data. | CVE Database V5 | ||
| High | 8.8 | EPSS 0.4% | High8.8EPSS 0.4%CVE Database V5CVE-2026-107811 A vulnerability in 0xJacky's nginx-ui versions 2.0.0 through 2.4.x allows authenticated users to access sensitive node tokens via specific API endpoints. These tokens can be used to bypass cross-node authentication, enabling impersonation of trusted nodes within the cluster. This can expose sensitive management operations such as configuration synchronization and service restart. The issue is resolved in version 2.5.0. | CVE Database V5 | ||
| High | 8.1 | EPSS 0.4% | CVE-2026-107810nginx-ui · Link Following High8.1EPSS 0.4%CVE Database V5CVE-2026-107810 CVE-2026-107810 is a high-severity vulnerability in 0xJacky's nginx-ui versions from 2.0.0 up to but not including 2.5.0. It involves improper link resolution before file access in the backup and restore functionality, allowing an authenticated user with backup creation and restoration privileges to inject malicious symlinks. This can lead to persistent configuration injection or denial of service. The issue is fixed in version 2.5.0. | CVE Database V5 | ||
| High | 8.8 | EPSS 0.2% | CVE-2026-107809nginx-ui · Cross-Site Request Forgery (CSRF) High8.8EPSS 0.2%CVE Database V5CVE-2026-107809 ## Summary 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: ```typescript // 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. ```go // 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. ```go // 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. ```go // 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` | CVE Database V5 | ||
| High | 8.1 | EPSS 0.4% | CVE-2026-107808nginx-ui · Improper Authentication High8.1EPSS 0.4%CVE Database V5CVE-2026-107808 ## Summary nginx-ui supports two second-factor methods — TOTP (OTP) and WebAuthn passkeys — and reports an account as 2FA-enabled when **either** is configured. However, the password login endpoint (`POST /api/login`) only enforces a second factor when a **TOTP secret** is present. An account that has registered a **passkey but no TOTP** is logged in after password verification alone — the passkey is never requested. This silently downgrades a passkey-protected account to single-factor (password-only) authentication. ## Details The account's 2FA policy treats passkeys as a valid factor (`model/user.go`): ```go func (u *User) EnabledOTP() bool { return len(u.OTPSecret) != 0 } func (u *User) EnabledPasskey() bool { /* true if a passkey row exists */ } func (u *User) Enabled2FA() bool { return u.EnabledOTP() || u.EnabledPasskey() } func (u *User) AfterFind(_ *gorm.DB) error { u.EnabledTwoFA = u.Enabled2FA() // exposed to the UI as `enabled_2fa` return nil } ``` But the login handler only checks `EnabledOTP()` (`api/user/auth.go`, `Login`): ```go u, err := user.Login(json.Name, json.Password) ... if u.EnabledOTP() { // <-- only TOTP is enforced if json.OTP == "" && json.RecoveryCode == "" { c.JSON(http.StatusOK, LoginResponse{Message: "The user has enabled 2FA", Code: Enabled2FA}) // 199 user.BanIP(clientIP) return } if _, err = user.VerifyOTP(u, json.OTP, json.RecoveryCode); err != nil { /* ... */ } secureSessionID = user.SetSecureSessionID(u.ID) } // Passkey-only accounts fall through to here and receive a full session token: accessToken, err := user.GenerateJWT(u) ``` No branch requires a WebAuthn assertion during password login when `EnabledPasskey()` is true. The root cause is the mismatch between the **policy definition** (`Enabled2FA()` = OTP **or** passkey) and the **enforcement check** (`EnabledOTP()` only). The same `EnabledOTP()`-only gating in `RequireSecureSession()` (`internal/middleware/secure_session.go`) means passkey-only users are also exempted from step-up on sensitive actions. ## Proof of Concept Tested against nginx-ui built from source (`go build -tags unembed`) on `127.0.0.1:9000`, with WebAuthn configured and a victim account that has a registered passkey and **no** TOTP. The vulnerable code is identical on the production `main` branch (`api/user/auth.go` `Login` gates on `u.EnabledOTP()` only; verified at commit `6c86e5a`, 2026-05-17). Account state advertised by `GET /api/2fa_status`: ```json {"enabled":true,"otp_status":false,"passkey_status":true, ...} ``` Attacker logs in with **password only** (`POST /api/login`, encrypted params as the client normally sends): ``` HTTP 200 {"message":"ok","code":200,"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...."} ``` `code: 200` + a valid JWT = an authenticated session, with the passkey never used. For comparison, the identical account with a TOTP secret instead correctly returns the second-factor challenge: ``` HTTP 200 {"message":"The user has enabled 2FA","code":199} ``` | Account state | `POST /api/login` (password only) | |---|---| | Passkey registered, no TOTP | `code 200` + JWT — **2FA NOT enforced** | | TOTP registered | `code 199` — 2FA challenge enforced | This isolates the defect: the login path enforces OTP but ignores passkeys. ## Impact - Any account protected **only** by a passkey is reduced to password-only authentication. An attacker who obtains the password (phishing, reuse, leak) gains full access despite the registered security key. - In nginx-ui all authenticated users are effectively administrators and the terminal feature grants a host shell, so account takeover leads to full control of the managed nginx instance / host. - Users are given a false sense of security: the UI shows the account as 2FA-enabled while the second factor is not enforced at login. ## Remediation - Gate the second-factor decision on `u.Enabled2FA()` (not `u.EnabledOTP()`) in `Login`, in both SSO callbacks, and in `RequireSecureSession()`. - For a passkey-only user logging in with a password, return a "passkey assertion required" challenge and complete login only after a successful WebAuthn assertion (the `begin_passkey_login` / `finish_passkey_login` flow already exists and should be required as the second step). - Centralize session-token issuance so no login entry point can skip the 2FA decision. ## Affected components - `api/user/auth.go` — `Login` - `model/user.go` — `EnabledOTP`, `EnabledPasskey`, `Enabled2FA`, `AfterFind` - `api/user/2fa.go` — `get2FAStatus` - `internal/middleware/secure_session.go` — `RequireSecureSession` | CVE Database V5 | ||
| High | 8.8 | EPSS 0.3% | CVE-2026-107807nginx-ui · Cleartext Storage of Sensitive Information High8.8EPSS 0.3%CVE Database V5CVE-2026-107807 ## 1. Vulnerability Summary nginx-ui's `Node.Secret` is a master credential that bypasses all JWT/password authentication for the entire API. The application accepts this credential via a **URL query parameter** (`?node_secret=`), causing it to be recorded in plaintext in HTTP access logs, reverse proxy logs, browser history, and HTTP `Referer` headers. Additionally, the official cluster configuration format embeds node secrets directly into URL query strings stored in `app.ini` and environment variables, creating a systemic credential exposure pattern across the entire cluster deployment model. An attacker who gains read access to any log aggregation system, proxy log, or configuration file can extract the node secret and obtain full, persistent, unauthenticated administrative access to the nginx-ui API — including reading TLS private keys, modifying nginx configurations, and (when chained with Bug #1) achieving OS-level code execution. --- ## 2. Root Cause Analysis ### 2.1 Node Secret Accepted as URL Query Parameter The `getNodeSecret` function reads the credential from the URL query string as a fallback when the `X-Node-Secret` header is absent: [1](#3-0) This function is called in both `AuthRequired()` and `AuthRequiredWS()` middleware, meaning the query parameter bypass works for **all authenticated HTTP and WebSocket endpoints**: [2](#3-1) [3](#3-2) The same pattern is repeated in the WebSocket origin checker, which also reads `node_secret` from the URL: [4](#3-3) ### 2.2 Node Secret Is a Full Authentication Bypass The documentation explicitly states this is by design: [5](#3-4) When the secret matches, the middleware sets the request context to an admin-level init user and calls `c.Next()` — bypassing all JWT validation, session checks, and 2FA: [2](#3-1) ### 2.3 Cluster Configuration Embeds Node Secrets in URLs The official cluster configuration format, documented and used in `app.example.ini`, stores node secrets as URL query parameters: [6](#3-5) The `parseNodeUrl` function extracts the secret from the URL's query string and stores it in the database as the node's `Token` field: [7](#3-6) This means node secrets are embedded in: - `app.ini` on disk (readable by any process with filesystem access) - The `NGINX_UI_CLUSTER_NODE` environment variable (visible in `ps aux`, Docker inspect, Kubernetes pod specs, CI/CD logs) - The SQLite database `nodes` table as the `token` column in plaintext ### 2.4 Node Secret Generation Uses UUID The secret is auto-generated as a UUID v4 if not set: [8](#3-7) UUID v4 has 122 bits of entropy, which is adequate. However, the exposure surface described in this report makes entropy irrelevant — the secret is leaked through operational channels, not brute-forced. --- ## 3. Exposure Surface The following table maps each exposure vector to its source in the codebase: | Vector | How It Happens | Who Can See It | |---|---|---| | **HTTP access logs** | `GET /api/settings?node_secret=xxx` logged by nginx/caddy/apache | Log readers, SIEM operators | | **Application logs** | Gin debug mode logs full request URLs | Server operators, log aggregators | | **Browser history** | Admin uses `?node_secret=` URL directly | Anyone with browser access | | **HTTP Referer header** | Page with `?node_secret=` in URL links to external resource | Third-party servers | | **WebSocket URL logs** | `ws://host/api/ws?node_secret=xxx` logged by proxies | Proxy log readers | | **`app.ini` on disk** | Cluster node URLs contain `node_secret=` | Filesystem readers | | **Environment variables** | `NGINX_UI_CLUSTER_NODE=...&node_secret=...` | `ps aux`, Docker inspect, K8s pod specs | | **CI/CD pipeline logs** | Env vars printed during deployment | CI/CD log viewers | | **Database** | `nodes.token` column stored in plaintext SQLite | DB file readers | --- ## 4. Proof of Concept ### Scenario A: Log-Based Secret Extraction **Step 1 — Attacker gains read access to nginx access logs** (e.g., via a misconfigured log aggregator, a compromised monitoring account, or a separate vulnerability). **Step 2 — Search logs for the pattern:** ```bash grep -oP 'node_secret=[^&\s"]+' /var/log/nginx/access.log # Output: node_secret=a1b2c3d4-e5f6-7890-abcd-ef1234567890 ``` **Step 3 — Use the extracted secret for full API access:** ```http GET /api/settings HTTP/1.1 Host: target:9000 X-Node-Secret: a1b2c3d4-e5f6-7890-abcd-ef1234567890 ``` Response: Full settings JSON including `JwtSecret`, `NodeSecret`, all nginx paths, and all configured credentials. ```http GET /api/nginx/config?filepath=/etc/nginx/nginx.conf HTTP/1.1 Host: target:9000 X-Node-Secret: a1b2c3d4-e5f6-7890-abcd-ef1234567890 ``` Response: Full nginx configuration including any embedded credentials. ### Scenario B: Environment Variable Exposure in Docker/Kubernetes **Step 1 — Attacker reads a Kubernetes pod spec or Docker Compose file:** ```yaml environment: - NGINX_UI_CLUSTER_NODE=http://10.0.0.1:9000?name=node1&node_se | CVE Database V5 | ||
| Critical | 9.4 | EPSS 0.4% | CVE-2026-107806nginx-ui · Code Injection Critical9.4EPSS 0.4%CVE Database V5CVE-2026-107806 A critical code injection vulnerability (CWE-94) exists in 0xJacky's nginx-ui versions from 2.3.8 up to but not including 2.5.0. An authenticated administrator with an active secure session can submit malicious backup key material and manifest to the restore API endpoint, which leads to replacement of the live configuration file including protected command settings. This allows execution of attacker-controlled commands in the Nginx UI runtime context, impacting confidentiality, integrity, and availability. The issue is fixed in version 2.5.0. | CVE Database V5 | ||
| High | 7.5 | EPSS 0.5% | CVE-2026-107805nginx-ui · Uncontrolled Resource Consumption High7.5EPSS 0.5%CVE Database V5CVE-2026-107805 CVE-2026-107805 is a high-severity vulnerability in 0xJacky's nginx-ui versions from 2.5.0 up to but not including 2.6.0. It involves uncontrolled resource consumption due to temporary file staging of attacker-controlled request bodies before signature validation. This can lead to denial of service by exhausting filesystem and processing resources. The issue affects availability only and does not impact authentication, confidentiality, or integrity. The vulnerability is fixed in version 2.6.0. | CVE Database V5 |
Showing 1–20 of 36 results