Listen to this Post
The vulnerability exists because the WebSocket endpoint `/api/v1/ws/server` uses an optional authentication middleware but fails to enforce per‑server ownership or admin role checks. When a non‑admin authenticated user connects, the code in `ws.go:123-139` treats any `CtxKeyAuthorizedUser` as a “member” and sets authorized = true. This boolean is passed to `getServerStat` (lines 160‑184), where `authorized` triggers `singleton.ServerShared.GetSortedList()` instead of the guest list. `GetSortedList()` returns all servers in the system without filtering by UserID. Additionally, `server.Host` is not redacted, exposing full host telemetry. Meanwhile, the normal REST endpoint `/api/v1/server` uses `listHandler` and `HasPermission()` (from common.go:44-56), which correctly restricts members to their own servers. The WebSocket streamed model (server_api.go:5-20) includes sensitive fields such as agent version, CPU/GPU names, memory/disk/swap totals, live resource usage, network traffic, temperatures, and GPU utilization. An attacker only needs a valid JWT for any non‑admin account. The endpoint is exposed by default (dashboard API). Static analysis confirms no call to `server.HasPermission(c)` in the WebSocket path. Affected commit `85b0dd2` (v2.0.7-1-g85b0dd2). The fix requires adding object‑level authorization inside the WebSocket loop.
Platform: Nezha Dashboard
Version: v2.0.7-1-g85b0dd2
Vulnerability: Horizontal info disclosure
Severity: Medium
date: 2026-05-22
Prediction: 2026-06-15
What Undercode Say:
Simulate unauthorized access to all servers via WebSocket curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \ -H "Cookie: nz-jwt=<non-admin-token>" \ http://127.0.0.1:8008/api/v1/ws/server Compare with filtered REST API curl -H "Cookie: nz-jwt=<non-admin-token>" \ http://127.0.0.1:8008/api/v1/server | jq '.[].id'
Exploit:
- Create two non‑admin users, each owning at least one server.
2. Authenticate as user A, obtain JWT.
- Open WebSocket connection to `/api/v1/ws/server` with that JWT.
- Receive JSON stream containing all servers (including user B’s servers) with full host details.
- Observe that REST `/api/v1/server` returns only user A’s servers.
Protection from this CVE:
- Upgrade to a patched version once released (expected by 2026-06-15).
- Apply the remediation: in
getServerStat, for authenticated non‑admin users, filter `serverList` to only those whereserver.UserID == userId. - Temporarily restrict access to `/api/v1/ws/server` via reverse proxy (e.g.,
location /api/v1/ws/server { deny all; }) if WebSocket monitoring is not required. - Enforce admin‑only WebSocket access by checking `user.Role == RoleAdmin` before streaming.
Impact:
Authenticated low‑privileged member can continuously monitor all users’ server inventory, live telemetry (CPU/GPU, memory, disk, network, temps, processes), platform versions, agent versions, geographic hints (country code), and last‑active timestamps. This leaks infrastructure composition, usage patterns, and operational state across tenants.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

