Loading...
Skip to main content

CVE-2026-62283 — Vulnerability in github.com/nezhahq/nezha — CVE...

CRITICAL

Nezha vulnerable to cross-tenant terminal/file-manager session hijack via WebSocket stream UUID without ownership check

Published June 26, 2026Updated August 22, 2026Source: osv

Summary

### Summary In nezha **v1.14.13–v1.14.14** and **v2.0.0–v2.0.9**, the WebSocket endpoints `GET /ws/terminal/:id` and `GET /ws/file/:id` authenticate the caller only by the presence of a valid stream UUID, with no ownership check tying that UUID to the user who created the stream. Any authenticated dashboard user (including a `RoleMember`) who learns a live stream UUID can attach to the session and gain interactive shell access or full file-manager control on the target server — i.e. cross-tenant RCE. This was silently fixed in commit [`6661d6a`](https://github.com/nezhahq/nezha/commit/6661d6a7fc1c269f55c7f4e775082ad23fbe0f54) (2026-05-18, shipped in v2.0.10). At submission time no public CVE/GHSA covers this fix, so operators of v1.14.x and pre-v2.0.10 v2.x deployments have no signal that they are running vulnerable code. ### Details **Stream allocation — `service/rpc/io_stream.go` (v2.0.9):** ```go func (s *NezhaHandler) CreateStream(streamId string) { s.ioStreamMutex.Lock() defer s.ioStreamMutex.Unlock() s.ioStreams[streamId] = &ioStreamContext{ userIoConnectCh: make(chan struct{}), agentIoConnectCh: make(chan struct{}), } } ``` No creator is bound to the stream. **Stream attach — `cmd/dashboard/controller/terminal.go` (v2.0.9):** ```go // @Router /ws/terminal/{id} [get] func terminalStream(c *gin.Context) (any, error) { streamId := c.Param("id") if _, err := rpc.NezhaHandlerSingleton.GetStream(streamId); err != nil { return nil, err } defer rpc.NezhaHandlerSingleton.CloseStream(streamId) // ... WebSocket upgrade and bidirectional pipe ... } ``` The only authorization check is `GetStream(streamId)` — "does this UUID exist in the in-memory map". `getUid(c)` is never compared against the user who called `createTerminal`. The same pattern is present in `fmStream(c)` in `cmd/dashboard/controller/fm.go`. **Where the UUID leaks:** `createTerminal` returns the UUID to the legitimate client, which then opens `wss://<dashboard>/ws/terminal/<UUID>`. As a URL path component the UUID is exposed via: - Reverse-proxy access logs (nginx, Caddy, Cloudflare). - Referer headers when the page embeds external resources or error reporters. - Browser history / bookmark sync. - Frontend telemetry (Sentry, Bugsnag) breadcrumbs that include the WebSocket URL. - Any shared-tenant or multi-operator log viewer. Any authenticated user with access to one of these side channels can attach to a live session. ### PoC 1. Deploy nezha v2.0.9. Add at least one server. Configure two accounts: `admin` (RoleAdmin, owns the server) and `member` (RoleMember, no access to that server). 2. As `admin`, open the web terminal for the server. The browser opens `wss://<dashboard>/ws/terminal/<UUID>`. Capture this UUID from the network inspector, server access log, or `Referer` header. 3. From a separate session logged in as `member`, open `wss://<dashboard>/ws/terminal/<UUID>` (same UUID). The member's WebSocket attaches to the same `ioStreamContext` because `terminalStream` only checks `GetStream(streamId)` — no ownership check. 4. The member can now read the admin's shell output and inject keystrokes, achieving shell-level RCE on the target server, with no visible signal to the legitimate session owner. Same flow works against `/ws/file/:id` (file-manager hijack: arbitrary read/write on the target server's filesystem). ### Impact - **Severity**: Critical. Interactive RCE on a server administered by another user, with no audit signal to the rightful session owner. - **Attack complexity**: Low. The attacker needs an authenticated dashboard account (which any `RoleMember` is) and one captured UUID from a side channel. - **Confidentiality / Integrity / Availability**: all High. `/ws/file/:id` exposes arbitrary read+write on the target filesystem; `/ws/terminal/:id` is a full shell. This is the same impact tier as CVE-2026-46716 (cross-tenant cron RCE) and arguably worse, because the entry point is a passively-leaked URL rather than an authenticated POST — attackers do not need direct dashboard interaction once the UUID is leaked through logs or telemetry. ### Fix reference Already fixed in master by commit [`6661d6a`](https://github.com/nezhahq/nezha/commit/6661d6a7fc1c269f55c7f4e775082ad23fbe0f54) ("fix(rpc): bind io_stream sessions to creator to prevent terminal/fm hijack"): - `CreateStream` now accepts a `creatorUserID uint64` and stores it on the `ioStreamContext`. - New `IsStreamAuthorizedForUser(streamId, userID, isAdmin)` helper. - `terminalStream` and `fmStream` call this helper **before** the WebSocket upgrade and **before** the `defer CloseStream(streamId)`, so a rejected attempt does not tear down a legitimate stream. Shipped in v2.0.10 (2026-05-19). The v1.14 line has not received a backport. ### Why this advisory The fix landed silently. The other May 17–21 fixes received public GHSAs (GHSA-99gv-2m7h-3hh9, GHSA-rxf6-wjh4-jfj6, GHSA-hvv7-hfrh-7gxj, GHSA-w4g9-mxgg-j532, GHSA-6x26-5727-rrm9, GHSA-4g6j-g789-rghm) covering cron RCE, AlertRule trigger, telemetry leak, notification SSRF, DDNS SSRF, and agent forge-results respectively — but none cover the terminal / file-manager session hijack. This advisory closes that gap so operators of v1.14.x and v2.0.0–v2.0.9 know to upgrade. ### Recommended action - Publish this GHSA so v2.x operators below v2.0.10 see the alert in their dependency scanners. - Either backport `6661d6a` to a v1.14.15 release, or mark the v1.14 line end-of-life in `SECURITY.md` so operators understand the support boundary.

Advisory Timeline

  • First published June 26, 2026 (107 days ago).
  • Last revised August 22, 2026 — 57 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Go
Update github.com/nezhahq/nezha to 2.0.10 or later
go get github.com/nezhahq/nezha@v2.0.10

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (2)

Affects 1 ecosystem: go (1).

PackageEcosystemAffectedFixed In
github.com/nezhahq/nezha
go
All versions2.0.10
github.com/nezhahq/nezha
go
All versionsRange-based data available

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-639
    Insecure Direct Object Reference (IDOR)MITRE
  • CWE-862
    Missing AuthorizationMITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.9 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Frequently Asked Questions

What is CVE-2026-62283?
Nezha vulnerable to cross-tenant terminal/file-manager session hijack via WebSocket stream UUID without ownership check This vulnerability has been assigned a severity rating of CRITICAL (CVSS score: 9.9/10).
How do I check if my project is affected by CVE-2026-62283?
CVE-2026-62283 affects github.com/nezhahq/nezha. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-62283 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.9

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

GHSA-q6xx-5vr8-p898
GO-2026-5821

Related CVEs

  • CVE-2026-53519
    CRITICAL

    Nezha Monitoring: Pre-auth path traversal via /dashboard.. prefix confusion leaks jwt_secret_key

  • CVE-2026-46716
    CRITICAL

    Nezha Monitoring: RoleMember can run shell on every server (cross-tenant RCE) via POST /api/v1/cron

  • CVE-2026-107806
    CRITICAL

    Nginx UI: Authenticated Remote Code Execution via Backup Restore App Config Overwrite

  • CVE-2026-68582
    CRITICAL

    Vikunja: Link-share token reads any tenant's kanban buckets and enumerates usernames/IDs instance-wide (BOLA)

  • CVE-2026-46717
    HIGH

    Nezha Monitoring: RoleMember-reachable SSRF with full response-body reflection via POST /api/v1/notification

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies