Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessAuthenticate as authorized caller on shared executor
-
DeliveryStart overlapping subscription on OPEN socket
-
Exploitsubscribe() overwrites single onmessage handler
-
ExecutionDATA frames delivered without id check
-
ImpactReceive victim's subscription payloads, starve victim
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V14 - Data Protection Data exposure prevention
MITRE ATT&CK
2 techniques across 2 tactics: Collection, Discovery The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Four concrete preconditions from the advisory must all hold: (1) a single executor value returned by buildWSLegacyExecutor is reused across callers rather than built per operation; (2) two subscription iterators overlap on an already-OPEN WebSocket, so ensureWebsocket() reuses the socket and the single mutable websocket.onmessage is overwritten; (3) the attacker can cause their own subscription request through that shared executor while the victim's subscription is active and acknowledged (no control over the downstream server is needed); and (4) downstream subscription results differ by user or authorization context so a misrouted payload is an actual disclosure. Limiting factors: the attacker must be an authorized caller on the shared executor (PR:L), the subscriptions must overlap in time (reflected in AC:H/AT:P), and the legacy graphql-ws protocol path must be in use. Applications that construct a new executor per operation - as the in-repo UrlLoader wrapper does at packages/loaders/url/src/index.ts:262-295 - are not affected by the cross-caller leak. |
| Impact | This is a genuine but conditional confidentiality issue, not a high-urgency widespread threat. The vendor-supplied CVSS 4.0 vector (AV:N/AC:H/AT:P/PR:L/UI:N/VC:H/VI:N/VA:L) scores 6.0 (Medium): network-reachable, but with high attack complexity and a present attack requirement (AT:P) reflecting the need for two subscriptions to overlap on an already-OPEN shared socket, plus low privileges (PR:L) because the attacker must be an authorized caller using the same shared executor. Impact is high confidentiality (VC:H, reading another user's authorized subscription payloads) with low availability impact (VA:L, the victim's stream is starved) and no integrity impact. No EPSS score and no KEV listing are provided in the input, and there is no confirmed standalone public exploit; exploitation status is therefore 'no public exploit identified at time of analysis,' although the GHSA advisory documents a verified dynamic reproduction against the published package 1.1.33. The vuln.today Decision label is this_month, consistent with a real, prioritize-this-cycle issue rather than an emergency. The decisive caveat - stated explicitly by the advisory - is that exploitability depends entirely on the consuming application's data flow: it is only exploitable when one executor instance from buildWSLegacyExecutor is shared across mutually untrusted callers, and the full set of affected downstream consumers is unknown. Applications that build a fresh executor per operation (as the in-repo UrlLoader wrapper does) are not affected. |
| Exploit ScenarioDerived | An authorized user of a GraphQL gateway or stitched-schema service that constructs one legacy-WS executor and reuses it per request starts their own subscription while a victim's subscription is active and acknowledged on the same OPEN WebSocket. Because subscribe() overwrites the single websocket.onmessage handler and the DATA branch delivers payloads without comparing data.id to the operation id, the attacker's observer receives the victim's private subscription payloads verbatim with the victim's authorization context, while the victim's stream is starved. The GHSA advisory documents a verified dynamic reproduction of this against published package 1.1.33, though no standalone public exploit is referenced. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 28, 2026
GraphQL Tools' legacy WebSocket executor (@graphql-tools/executor-legacy-ws, versions through 1.1.35) discloses subscription payloads across callers: buildWSLegacyExecutor keeps a single WebSocket in closure state and reassigns its only websocket.onmessage handler on every subscribe(), and the LEGACY_WS.DATA branch forwards data.payload to the newest observer without comparing data.id to the operation id it created - so an authorized caller who starts an overlapping subscription through the same shared executor receives another user's authorized subscription data while the earlier caller's stream is silenced. The issue is conditional rather than broadly exploitable: it requires one executor instance reused across mutually untrusted callers, overlapping subscriptions on an already-OPEN socket, and per-user differences in subscription results (reflected in the assessed CVSS 3.1 vector AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:L); applications that build a fresh executor per operation, such as the in-repo UrlLoader wrapper, are not affected. No CISA KEV entry or other active-exploitation signal is present in the available data, and the vendor advisory documents a reproduction harness verified against the published 1.1.33 package, which is a public PoC reference rather than confirmed working exploit code; the vendor has released 1.1.36 as the fix.
RemediationAI
Vendor-released patch: upgrade @graphql-tools/executor-legacy-ws to 1.1.36 (release tag https://github.com/ardatan/graphql-tools/releases/tag/@graphql-tools/executor-legacy-ws@1.1.36), delivered by PR https://github.com/ardatan/graphql-tools/pull/8480 and commit https://github.com/ardatan/graphql-tools/commit/c2f226e6f68236be9e4a577f29faeaa92547458b; EUVD records graphql-tools < 9.0.36 for the monorepo package, so pin the executor to 1.1.36 or a release that depends on it. Be aware that 1.1.36 changes runtime behavior - each execution now opens its own WebSocket and sends its own connection_init, and connectionParams from request extensions no longer persist across requests - so connection counts rise and any code relying on socket/session reuse or on inherited connection params must be reviewed. If upgrading is not immediately possible, the documented safe pattern is to stop sharing executor state: construct a new executor per operation (the approach used by the UrlLoader wrapper at packages/loaders/url/src/index.ts:262-295) instead of reusing one buildWSLegacyExecutor result across mutually untrusted callers, accepting the added connection setup cost and the loss of socket reuse. Advisory detail: https://github.com/ardatan/graphql-tools/security/advisories/GHSA-mp66-8ww2-pcwm. No CISA KEV listing or active-exploitation signal appears in the available data, and the priority label places this in the current monthly patch cycle rather than an emergency window.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 3 packages in npm, euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The affected component implements a client for the legacy graphql-ws WebSocket subprotocol, where a single socket multiplexes operations identified by an id: CONNECTION_INIT/CONNECTION_ACK establish the session, START/CONNECTION_TERMINATE manage it, and DATA/ERROR/COMPLETE frames are tagged with the operation id they belong to. buildWSLegacyExecutor's closure holds one WebSocket and its ensureWebsocket() helper (packages/executors/legacy-ws/src/index.ts:35-42) deliberately reuses a socket that is already OPEN instead of opening a new one; subscribe() then installs the message handler by assigning to the socket's single mutable websocket.onmessage property (index.ts:109-113), which detaches the previous subscriber. Two independent defects follow: the overwritten handler detaches the earlier observer, and the LEGACY_WS.DATA case calls observer.next(data.payload) without checking data.id against the id generated at line 103 and sent with START at line 123 (index.ts:114-147), so frames for other operations land on the newest observer. Operation ids were derived from Date.now(), so they were not collision-resistant either. The underlying weakness class is CWE-200 (exposure of sensitive information to an unauthorized actor) realized as cross-tenant subscription misrouting inside a shared executor, not a memory-safety flaw. The upstream fix (PR 8480, commit c2f226e) restructures the executor so each execution opens its own socket, builds connection_init from the base connectionParams plus that request's extensions.connectionParams only, delivers data/error/complete frames only when the id matches the operation that socket started, and replaces Date.now() ids with a sequence-plus-random value; the same changeset also closes GHSA-434m-5hcj-pxf3 (CWE-613), where connection params leaked from a previous caller's connection_init. Note that the protection in packages/loaders/url/src/index.ts:262-295 comes from rebuilding the executor per request, not from any id validation inside the executor.
Know when Graphql Tools gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:H/VI:N/VA:L/SC:N/SI:N/SA:N
Network-reachable but needs two overlapping subscriptions (AC:H) and an authorized caller on the shared executor (PR:L); discloses another user's data (C:H) and starves their stream (A:L), with no integrity impact.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
1DescriptionCVE.org
GraphQL Tools provides utilities for building, stitching, and mocking GraphQL schemas. Prior to version 1.1.36 of the GraphQL Tools legacy WebSocket executor package, buildWSLegacyExecutor in packages/executors/legacy-ws/src/index.ts reuses one WebSocket and replaces its single websocket.onmessage handler whenever a new overlapping subscription starts. The handler delivers LEGACY_WS.DATA frames to the newest observer without comparing data.id with the subscription operation id, so a caller using the same executor can receive another user's authorized subscription payload while the earlier caller's stream is starved. This issue is fixed in version 1.1.36 of the GraphQL Tools legacy WebSocket executor package.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.
More in Graphql Tools
View allThis affects the package @graphql-tools/git-loader before 6.2.6. Rated high severity (CVSS 8.8), this vulnerability is r
Stale authentication state in GraphQL Tools' legacy WebSocket executor lets a later caller inherit a previous caller's d
TLS certificate validation is disabled by default in @graphql-tools/executor-legacy-ws prior to 1.1.35, where buildWSLeg
EUVD-2026-112473
GHSA-mp66-8ww2-pcwm
NVD
CVE.org
Exploit-DB