## 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
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.
Improper neutralization of special elements used in an SQL command ('SQL injection') vulnerability in wp-post-author.
This issue affects wp-post-author version 4.0.0 prior to 4.1.0.
CVE-2026-15340 is a critical buffer overflow vulnerability in the lwIP SMTP client from Savannah. The client does not properly check the size of inputs, which can lead to memory corruption. This vulnerability has a CVSS score of 9.8, indicating high impact on confidentiality, integrity, and availability. It affects version 2.2.1 of the lwIP SMTP client. No patch or remediation information is currently provided.
Improper neutralization of special elements used in an SQL command ('SQL injection') vulnerability in wp-post-author.
This issue affects wp-post-author before 4.1.0.
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.
## Summary
In Nginx UI versions 2.2.0 through 2.5.x, the official bundled reverse-proxy topology did not preserve the external client identity used by Gin. The backend treated the local proxy peer as the client because no trusted proxy was configured, while the proxy supplied the actual address in forwarding headers.
## Impact
This has two distinct effects in bundled-proxy deployments:
* **IP allowlist enforcement:** management API requests forwarded by the bundled proxy were identified as loopback and could pass the loopback exception even when the external source was not in the configured allowlist. Protected management operations still required valid credentials; this did not grant unauthenticated administrator access.
* **Login availability:** failed login attempts from different external sources were attributed to one loopback address. An unauthenticated attacker could therefore trigger the shared temporary login-ban threshold and deny password or OTP login to other users behind the proxy until the ban expired. Existing authenticated sessions were not invalidated.
## Remediation
Upgrade to Nginx UI 2.6.0 or later. The fix explicitly trusts only the intended bundled proxy, validates configured trusted proxies, uses the resolved client address consistently, and fails closed when an IP allowlist is enabled but the client address is invalid.
Fix commit: https://github.com/0xJacky/nginx-ui/commit/e30e331303fc21cf077a2bea724bd79e66892eaf
CVE-2026-95702 is a use-after-free vulnerability in the virtual file system (VFS) component of Google gVisor prior to release 20260831.0. It allows a local attacker with standard container privileges to execute code in the host sentry process by triggering a double-free of the backing MemoryFile in an in-sandbox overlay filesystem. The sentry process remains confined by Linux seccomp and namespace boundaries on the host.
CVE-2026-33272 affects Red Lion Controls 700 Series switches. A malicious user with physical access can boot the device from factory settings without authentication, use default administrative credentials to gain administrative access, and save persistent configuration changes. This vulnerability allows unauthorized configuration changes but does not impact availability.
CVE-2026-39453 is a vulnerability in Red Lion Controls 700 Series switches where navigating to a specific URL on the device's web server causes it to reboot. This behavior can be exploited to create denial-of-service (DoS) conditions by repeatedly triggering the reboot via automated tools like curl.
CVE-2026-29797 affects Red Lion Controls 700 Series devices by allowing firmware or bootloader updates without any authentication. This vulnerability enables attackers to push malicious files to the device easily. Additionally, attackers with the same software can scan networks for N-Tron devices and push or pull firmware using SNMP/TFTP without authentication.
CVE-2026-33367 is a high-severity vulnerability in Red Lion Controls 700 Series devices where SNMP allows unauthenticated administrative actions. This includes retrieving configuration files, modifying user accounts or device settings, and initiating firmware or bootloader upgrades or downgrades without any authentication.
CVE-2026-28745 affects Red Lion Controls 700 Series devices where usernames and passwords, including default credentials, are stored in configuration files using weak encryption. If an attacker knows the default credentials, they could potentially retrieve other stored credentials. The vulnerability has a high severity score of 7.5 but no known exploits in the wild. No patch or remediation information is currently available.
PHPNuxBill through 2025.3.20 contains an account takeover vulnerability in the customer password reset flow in system/controllers/forgot.php that allows unauthenticated attackers to brute-force the 6-digit otp_code. Attackers knowing a customer username can guess the code without attempt limits or lockout, then read the newly set password from the HTTP response to hijack the account.
CVE-2026-108108 is an authentication bypass vulnerability in PHPNuxBill through version 2025.3.20. The flaw exists in the RADIUS CHAP verification process where Password::chap_verify() incorrectly returns true even when the supplied response does not match the expected value. This allows attackers who know a valid customer or PPPoE username to log in via MikroTik hotspot or PPPoE CHAP with any incorrect password, gaining unauthorized network access and potentially consuming that customer's plan.
PHPNuxBill through 2025.3.20 contains an unauthenticated SQL injection vulnerability in the radius.php FreeRADIUS REST endpoint that interpolates request parameters into whereRaw() queries. Attackers can send crafted username, macAddr or nasid parameters to the accounting or authenticate actions to extract customer records and credentials via time-based blind SQL injection.
CVE-2026-108106 is a high-severity vulnerability in xerial snappy-java before version 1.1.10.9. It involves unbounded memory allocation when processing compressed input with a large declared uncompressed length. Attackers can exploit this by supplying crafted bytes to various Snappy decompression functions, causing the JVM to allocate up to 2 GB of memory and potentially triggering an OutOfMemoryError, resulting in denial of service.
Xerial snappy-java from 1.1.7.4 before 1.1.10.10 contains a double release vulnerability in SnappyFramedInputStream that returns pooled buffers twice when replacement allocation fails. Attackers can supply framed data with a large declared chunk length to trigger OutOfMemoryError, causing shared backing arrays that expose or overwrite other streams' decompressed data.
CVE-2026-39460 affects Red Lion Controls 700 Series devices where usernames and passwords, including default factory credentials, are stored in plaintext within the configuration file. An attacker with administrator rights can view this file via the CLI or export it through a TFTP transfer initiated from the web interface. Additionally, a TFTP transfer can be triggered via SNMP without requiring authentication, increasing the risk of credential exposure.
CVE-2026-104115 is a stack-based buffer overflow vulnerability in the illumos reparse point daemon (reparsed). It allows a local user to crash the daemon by sending an nfs-basic request with an overlong host or path component. The flaw arises because the daemon copies these components into a fixed 1024-byte stack buffer without length checks. Systems built with stack protection will abort the daemon on overflow, causing the related filesystem reparse service to enter maintenance mode. This service is disabled by default. The vulnerability has existed since 2009 and affects illumos distributions prior to a specific commit fixing the issue.