{"id":"EUVD-2026-64139","revision":null,"records":[{"revision":"9ba055e040304955a728a59a55d6f7c3","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-62283","aliases":[],"title":"Nezha Monitoring: Cross-tenant terminal/file-manager session hijack via WebSocket stream UUID without ownership check","description":"Nezha Monitoring is a self-hostable, lightweight, servers and websites monitoring and O&M tool. Nezha versions 1.14.13 through 1.14.14 and 2.0.0 through 2.0.9 do not bind stream identifiers created by CreateStream in service/rpc/io_stream.go to their creating user, and `GET /ws/terminal/:id` and `GET /ws/file/:id` only check whether the supplied UUID exists. An authenticated RoleMember who obtains a live stream UUID from logs, browser history, referer data, or telemetry can attach to another user's terminal or file-manager session, read and write target-server files, and execute shell commands. This issue is fixed in version 2.0.10.","state":0,"publishedAt":"2026-08-21T20:21:28.712+00:00","modifiedAt":"2026-08-21T21:42:51.779+00:00","affected":[{"ecosystem":"Vendor product","name":"nezha","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"nezhahq\",\n                    \"product\": \"nezha\",\n                    \"versions\": [\n                        {\n                            \"version\": \">= 1.14.13, <= 1.14.14\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 2.0.0, < 2.0.10\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","score":9.9,"severity":"CRITICAL"}],"references":["https://github.com/nezhahq/nezha/security/advisories/GHSA-q6xx-5vr8-p898","https://github.com/nezhahq/nezha/commit/6661d6a7fc1c269f55c7f4e775082ad23fbe0f54","https://github.com/nezhahq/nezha/releases/tag/v2.0.10"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-62283","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-62283","identifiers":["CVE-2026-62283"]},"retained":false,"historicalAffected":[]},{"revision":"ea60ff1632d44d2a8b9b1c2bb8512479","observedAt":"2026-11-09T14:11:27.68+00:00","statement":{"source":"euvd","id":"EUVD-2026-64139","aliases":["CVE-2026-62283"],"title":"Nezha Monitoring is a self-hostable, lightweight, servers and websites monitoring and O&M tool. Nezha versions 1.14.13 through 1.14.14 and 2.0.0 through 2.0.9 do not bind stream identifiers created by CreateStream in service/rpc/io_stream.g…","description":"Nezha Monitoring is a self-hostable, lightweight, servers and websites monitoring and O&M tool. Nezha versions 1.14.13 through 1.14.14 and 2.0.0 through 2.0.9 do not bind stream identifiers created by CreateStream in service/rpc/io_stream.go to their creating user, and `GET /ws/terminal/:id` and `GET /ws/file/:id` only check whether the supplied UUID exists. An authenticated RoleMember who obtains a live stream UUID from logs, browser history, referer data, or telemetry can attach to another user's terminal or file-manager session, read and write target-server files, and execute shell commands. This issue is fixed in version 2.0.10.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","score":9.9,"severity":null}],"references":["https://github.com/nezhahq/nezha/security/advisories/GHSA-q6xx-5vr8-p898","https://github.com/nezhahq/nezha/commit/6661d6a7fc1c269f55c7f4e775082ad23fbe0f54","https://github.com/nezhahq/nezha/releases/tag/v2.0.10"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-64139","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Aug 21, 2026, 8:21:28 PM","dateUpdated":"Aug 21, 2026, 9:42:51 PM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-64139","identifiers":["EUVD-2026-64139","CVE-2026-62283"]},"retained":false,"historicalAffected":[]},{"revision":"c048d7def0294e2794fb3872dde960b8","observedAt":"2026-10-25T14:19:28.838+00:00","statement":{"source":"nvd","id":"CVE-2026-62283","aliases":[],"title":"Nezha Monitoring is a self-hostable, lightweight, servers and websites monitoring and O&M tool. Nezha versions 1.14.13 through 1.14.14 and 2.0.0 through 2.0.9 do not bind stream identifiers created by CreateStream in service/rpc/io_stream.g…","description":"Nezha Monitoring is a self-hostable, lightweight, servers and websites monitoring and O&M tool. Nezha versions 1.14.13 through 1.14.14 and 2.0.0 through 2.0.9 do not bind stream identifiers created by CreateStream in service/rpc/io_stream.go to their creating user, and `GET /ws/terminal/:id` and `GET /ws/file/:id` only check whether the supplied UUID exists. An authenticated RoleMember who obtains a live stream UUID from logs, browser history, referer data, or telemetry can attach to another user's terminal or file-manager session, read and write target-server files, and execute shell commands. This issue is fixed in version 2.0.10.","state":0,"publishedAt":"2026-08-21T21:17:01.183+00:00","modifiedAt":"2026-10-12T16:10:00.22+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","score":9.9,"severity":"CRITICAL"}],"references":["https://github.com/nezhahq/nezha/commit/6661d6a7fc1c269f55c7f4e775082ad23fbe0f54","https://github.com/nezhahq/nezha/releases/tag/v2.0.10","https://github.com/nezhahq/nezha/security/advisories/GHSA-q6xx-5vr8-p898"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-62283","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-639","CWE-862"],"productCriteria":[],"sourceDates":{"published":"2026-08-21T21:17:01.183","lastModified":"2026-10-12T16:10:00.220"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-62283","identifiers":["CVE-2026-62283"]},"retained":false,"historicalAffected":[]},{"revision":"e7c67152991a4b2da5528f68599735d6","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-q6xx-5vr8-p898","aliases":["CVE-2026-62283","GO-2026-5821"],"title":"Nezha vulnerable to cross-tenant terminal/file-manager session hijack via WebSocket stream UUID without ownership check","description":"### Summary\n\nIn 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.\n\nThis 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.\n\n### Details\n\n**Stream allocation — `service/rpc/io_stream.go` (v2.0.9):**\n\n```go\nfunc (s *NezhaHandler) CreateStream(streamId string) {\n    s.ioStreamMutex.Lock()\n    defer s.ioStreamMutex.Unlock()\n\n    s.ioStreams[streamId] = &ioStreamContext{\n        userIoConnectCh:  make(chan struct{}),\n        agentIoConnectCh: make(chan struct{}),\n    }\n}\n```\n\nNo creator is bound to the stream.\n\n**Stream attach — `cmd/dashboard/controller/terminal.go` (v2.0.9):**\n\n```go\n// @Router /ws/terminal/{id} [get]\nfunc terminalStream(c *gin.Context) (any, error) {\n    streamId := c.Param(\"id\")\n    if _, err := rpc.NezhaHandlerSingleton.GetStream(streamId); err != nil {\n        return nil, err\n    }\n    defer rpc.NezhaHandlerSingleton.CloseStream(streamId)\n    // ... WebSocket upgrade and bidirectional pipe ...\n}\n```\n\nThe 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`.\n\n**Where the UUID leaks:**\n\n`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:\n\n- Reverse-proxy access logs (nginx, Caddy, Cloudflare).\n- Referer headers when the page embeds external resources or error reporters.\n- Browser history / bookmark sync.\n- Frontend telemetry (Sentry, Bugsnag) breadcrumbs that include the WebSocket URL.\n- Any shared-tenant or multi-operator log viewer.\n\nAny authenticated user with access to one of these side channels can attach to a live session.\n\n### PoC\n\n1. 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).\n2. 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.\n3. 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.\n4. 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.\n\nSame flow works against `/ws/file/:id` (file-manager hijack: arbitrary read/write on the target server's filesystem).\n\n### Impact\n\n- **Severity**: Critical. Interactive RCE on a server administered by another user, with no audit signal to the rightful session owner.\n- **Attack complexity**: Low. The attacker needs an authenticated dashboard account (which any `RoleMember` is) and one captured UUID from a side channel.\n- **Confidentiality / Integrity / Availability**: all High. `/ws/file/:id` exposes arbitrary read+write on the target filesystem; `/ws/terminal/:id` is a full shell.\n\nThis 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.\n\n### Fix reference\n\nAlready 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\"):\n\n- `CreateStream` now accepts a `creatorUserID uint64` and stores it on the `ioStreamContext`.\n- New `IsStreamAuthorizedForUser(streamId, userID, isAdmin)` helper.\n- `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.\n\nShipped in v2.0.10 (2026-05-19). The v1.14 line has not received a backport.\n\n### Why this advisory\n\nThe 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.\n\n### Recommended action\n\n- Publish this GHSA so v2.x operators below v2.0.10 see the alert in their dependency scanners.\n- 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.","state":0,"publishedAt":"2026-06-26T22:31:41+00:00","modifiedAt":"2026-08-22T11:55:38.6428757+00:00","affected":[{"ecosystem":"Go","name":"github.com/nezhahq/nezha","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"1.14.13"},{"kind":"last_affected","version":"1.14.14"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"Go","name":"github.com/nezhahq/nezha","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"2.0.0"},{"kind":"fixed","version":"2.0.10"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"CRITICAL"}],"references":["https://github.com/nezhahq/nezha/security/advisories/GHSA-q6xx-5vr8-p898","https://github.com/nezhahq/nezha"],"sourceUrl":"https://github.com/advisories/GHSA-q6xx-5vr8-p898","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-q6xx-5vr8-p898","identifiers":["GHSA-q6xx-5vr8-p898","CVE-2026-62283","GO-2026-5821"]},"retained":false,"historicalAffected":[]},{"revision":"e8abd3ca5b464d92885b7041a952ab5f","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GO-2026-5821","aliases":["CVE-2026-62283","GHSA-q6xx-5vr8-p898"],"title":"Nezha vulnerable to cross-tenant terminal/file-manager session hijack via WebSocket stream UUID without ownership check in github.com/nezhahq/nezha","description":"Nezha vulnerable to cross-tenant terminal/file-manager session hijack via WebSocket stream UUID without ownership check in github.com/nezhahq/nezha.\n\nNOTE: The source advisory for this report contains additional versions that could not be automatically mapped to standard Go module versions.\n\n(If this is causing false-positive reports from vulnerability scanners, please suggest an edit to the report.)\n\nThe additional affected modules and versions are: github.com/nezhahq/nezha from v2.0.0 before v2.0.10.","state":0,"publishedAt":"2026-07-07T15:26:32+00:00","modifiedAt":"2026-08-22T11:55:38.6428757+00:00","affected":[{"ecosystem":"Go","name":"github.com/nezhahq/nezha","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"Go","name":"github.com/nezhahq/nezha","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"1.14.13"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[],"references":["https://github.com/nezhahq/nezha/security/advisories/GHSA-q6xx-5vr8-p898"],"sourceUrl":"https://osv.dev/vulnerability/GO-2026-5821","license":"OSV · upstream source license applies","key":"osv:GO-2026-5821","identifiers":["GO-2026-5821","CVE-2026-62283","GHSA-q6xx-5vr8-p898"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-10T10:21:23.1769119+00:00","complete":true,"records":1773,"lastAttemptAt":"2026-11-10T10:21:23.1769119+00:00","lastSuccessAt":"2026-11-10T10:21:23.4268898+00:00","error":null,"lastVerifiedAt":"2026-11-10T10:21:23.4268987+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-8859cf40d4337e24bd2f258cc7778fbad01bb24c79d057aaf34cf1dfc6f8917d-8bdcdeeb414e06ff50ed637d818ac25d52680d19f71fc0ebe3f4c4b3f836ed38","complete":true,"records":421927,"lastAttemptAt":"2026-11-10T10:21:22.8157744+00:00","lastSuccessAt":"2026-11-10T09:21:38.1064889+00:00","error":null,"lastVerifiedAt":"2026-11-10T10:21:22.8157744+00:00","snapshotPublishedAt":"2026-11-10T09:20:43+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-2e6a476534094233b48f2f0b6da5cf35","complete":true,"records":13689,"lastAttemptAt":"2026-11-10T10:21:50.2500014+00:00","lastSuccessAt":"2026-11-10T06:05:35.03+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:05:35.03+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13742,"expectedIdentifiers":13742,"failedIdentifiers":0},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-10T10:21:23.1769119+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-10T10:21:23.1769119+00:00","lastSuccessAt":"2026-11-10T10:21:23.4276529+00:00","error":null,"lastVerifiedAt":"2026-11-10T10:21:23.4276532+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-b0b0499af228434598651aa5d221386e","complete":false,"records":13695,"lastAttemptAt":"2026-11-10T10:21:49.6403901+00:00","lastSuccessAt":"2026-11-10T10:21:49.637+00:00","error":"100 identifier lookups failed; latest failures include request timeout. Other identifiers were checked independently.","lastVerifiedAt":"2026-11-10T10:21:49.637+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13642,"expectedIdentifiers":13742,"failedIdentifiers":100},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-cdffb4589856378aa42e8d1bd4a6c74e27a180d8160bf764c44715ef760f0a62","complete":true,"records":9932,"lastAttemptAt":"2026-11-10T10:21:23.1241572+00:00","lastSuccessAt":"2026-11-10T00:04:19.8260565+00:00","error":null,"lastVerifiedAt":"2026-11-10T10:21:23.1241572+00:00","snapshotPublishedAt":"2026-11-09T23:48:01+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-26503967ae4379db8f374089589d6e03fb15bd31f820c9e992aaf93840c2236c","complete":true,"records":1971,"lastAttemptAt":"2026-11-10T10:21:22.8858542+00:00","lastSuccessAt":"2026-11-09T21:02:20.472473+00:00","error":null,"lastVerifiedAt":"2026-11-10T10:21:22.8858542+00:00","snapshotPublishedAt":"2026-11-09T20:18:18+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-94169eec81ea3989aa551092397ff34ae53c104b4a6ce646e1524452e4ab2a39","complete":true,"records":3065,"lastAttemptAt":"2026-11-10T10:21:23.1397622+00:00","lastSuccessAt":"2026-11-10T08:04:45.5923716+00:00","error":null,"lastVerifiedAt":"2026-11-10T10:21:23.1397622+00:00","snapshotPublishedAt":"2026-11-10T06:48:01+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-4331051b0b2d4ccdbdca3aa196b0be3818a465064a4b18dde4cf39c2250eb490","complete":true,"records":231599,"lastAttemptAt":"2026-11-10T10:21:23.0142877+00:00","lastSuccessAt":"2026-11-10T08:04:37.1757322+00:00","error":null,"lastVerifiedAt":"2026-11-10T10:21:23.0142877+00:00","snapshotPublishedAt":"2026-11-10T07:33:02+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}