Every CVE Search/ Get API key

CVE-2026-118665

GraphQL Tools: Per-request connection parameters persist into later users' WebSocket authentications

8.2 HighFix available

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 retains request.extensions.connectionParams in the closure-scoped executorConnectionParams object after cleanupWebsocket closes a connection. When one executor is reused across different authorization contexts, a later request that omits a sensitive key can send an earlier caller's Authorization or tenant value in its connection_init payload, causing the downstream server to authenticate the later caller as the earlier user. Applications that create a new executor for every request are not affected. This issue is fixed in version 1.1.36 of the GraphQL Tools legacy WebSocket executor package.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
High
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.39%Unchanged since Oct 29, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.2

GraphQL Tools: Per-request connection parameters persist into later users' WebSocket authentications

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 retains request.extensions.connectionParams in the closure-scoped executorConnectionParams object after cleanupWebsocket closes a connection. When one executor is reused across different authorization contexts, a later request that omits a sensitive key can send an earlier caller's Authorization or tenant value in its connection_init payload, causing the downstream server to authenticate the later caller as the earlier user. Applications that create a new executor for every request are not affected. This issue is fixed in version 1.1.36 of the GraphQL Tools legacy WebSocket executor package.

Record
CVE-2026-118665
CVSS 4.0
8.2 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-613
Updated
2026-11-03
EUVDEUVD-2026-112472 8.2

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 retains request.extensions.connectionParams in the closure-scoped executorConnectionParams object after cleanupWebsocket closes a connection. When one executor is reused across different authorization contexts, a later request that omits a sensitive key can send an earlier caller's Authorization or tenant value in its connection_init payload, causing the downstream server to authenticate the later caller as the earlier user. Applications that create a new executor for every request are not affected. This issue is fixed in version 1.1.36 of the GraphQL Tools legacy WebSocket executor package.

Record
EUVD-2026-112472
CVSS 4.0
8.2 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Updated
2026-11-03
GitHub AdvisoriesGHSA-434m-5hcj-pxf3 8.2

GraphQL Tools: Per-request connection parameters persist into later users' WebSocket authentications

Stale authentication state in @graphql-tools/executor-legacy-ws: per-request extensions.connectionParams persist in executor closure state and are replayed in a later caller's connection_init

Report metadata

| Field | Value | | --- | --- | | Package | @graphql-tools/executor-legacy-ws (npm, pkg:npm/%40graphql-tools/executor-legacy-ws) | | Repository | https://github.com/ardatan/graphql-tools | | Component | buildWSLegacyExecutor (packages/executors/legacy-ws/src/index.ts) | | Vulnerability class | Stale authentication state / credential reuse across requests | | Verified against | Commit b5d1c36ebb8ed3868260ffee5bbcbb423ad5c1f1; npm release 1.1.33 installed and exercised. During validation the same behaviour was also observed on the current latest release 1.1.35, and the unreset closure is still present on master. | | API surface | Public documented API (buildWSLegacyExecutor, and request.extensions.connectionParams on the returned executor) | | Affected in default configuration | Yes — the factory returns a general, reusable Executor with no per-identity or single-use restriction, and no supported teardown clears the retained parameters. |

Version note: the originally recorded affected range was <= 1.1.33. Validation showed that range understates exposure — the same proof of concept leaks identically on 1.1.35.

Summary

buildWSLegacyExecutor keeps a single closure-scoped object, executorConnectionParams, for the lifetime of the executor. Every execution that carries request.extensions.connectionParams merges those keys into that object with Object.assign, and the object is merged into the connection_init payload each time a new WebSocket opens. Nothing ever removes keys: cleanupWebsocket terminates the socket and nulls the handle but leaves executorConnectionParams intact, and a later request that simply omits a key skips the conditional update entirely.

The consumer-side shape is a shared executor that forwards per-user credentials. When one long-lived executor serves multiple principals — the schema-stitching, gateway, or mesh pattern where each ExecutionRequest supplies its own extensions.connectionParams — a request that omits the auth key is sent to the downstream server with the previous caller's Authorization/tenant values in its connection_init, so the downstream server authenticates the later caller as the earlier user.

Behaviour of the neighbouring state in the same file:

  • WebSocket handle (websocket) → reset on teardown in cleanupWebsocket, lines 78-88
  • Per-request connectionParams merge, present case → applied as documented, lines 93-101
  • executorConnectionParams closure object → never reset; survives socket teardown and is re-sent on the next connection, line 32 and line 54

Impact

A caller who supplies no credentials (or lower-privileged ones) can have its downstream GraphQL subscription executed under a previous user's retained token or tenant value, and can receive data that its own connection_init would not authorize. The credential itself is never disclosed to the attacker — it reaches the sink through closure storage, not because the attacker knows it — but the downstream authorization it represents is.

The new capability versus safe behaviour: without this bug, an anonymous request would open a connection whose connection_init contains only base options…

Record
GHSA-434m-5hcj-pxf3
CVSS 4.0
8.2 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-613
Updated
2026-11-02
NVD 8.2

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 retains request.extensions.connectionParams in the closure-scoped executorConnectionParams object after cleanupWebsocket closes a connection. When one executor is reused across different authorization contexts, a later request that omits a sensitive key can send an earlier caller's Authorization or tenant value in its connection_init payload, causing the downstream server to authenticate the later caller as the earlier user. Applications that create a new executor for every request are not affected. This issue is fixed in version 1.1.36 of the GraphQL Tools legacy WebSocket executor package.

Record
CVE-2026-118665
CVSS 4.0
8.2 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-613
Updated
2026-11-03
OSV 8.2

GraphQL Tools: Per-request connection parameters persist into later users' WebSocket authentications

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 retains request.extensions.connectionParams in the closure-scoped executorConnectionParams object after cleanupWebsocket closes a connection. When one executor is reused across different authorization contexts, a later request that omits a sensitive key can send an earlier caller's Authorization or tenant value in its connection_init payload, causing the downstream server to authenticate the later caller as the earlier user. Applications that create a new executor for every request are not affected. This issue is fixed in version 1.1.36 of the GraphQL Tools legacy WebSocket executor package.

Record
CVE-2026-118665
CVSS 4.0
8.2 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-613
Updated
2026-11-07
OSVGHSA-434m-5hcj-pxf3 8.2

GraphQL Tools: Per-request connection parameters persist into later users' WebSocket authentications

Stale authentication state in @graphql-tools/executor-legacy-ws: per-request extensions.connectionParams persist in executor closure state and are replayed in a later caller's connection_init

Report metadata

| Field | Value | | --- | --- | | Package | @graphql-tools/executor-legacy-ws (npm, pkg:npm/%40graphql-tools/executor-legacy-ws) | | Repository | https://github.com/ardatan/graphql-tools | | Component | buildWSLegacyExecutor (packages/executors/legacy-ws/src/index.ts) | | Vulnerability class | Stale authentication state / credential reuse across requests | | Verified against | Commit b5d1c36ebb8ed3868260ffee5bbcbb423ad5c1f1; npm release 1.1.33 installed and exercised. During validation the same behaviour was also observed on the current latest release 1.1.35, and the unreset closure is still present on master. | | API surface | Public documented API (buildWSLegacyExecutor, and request.extensions.connectionParams on the returned executor) | | Affected in default configuration | Yes — the factory returns a general, reusable Executor with no per-identity or single-use restriction, and no supported teardown clears the retained parameters. |

Version note: the originally recorded affected range was <= 1.1.33. Validation showed that range understates exposure — the same proof of concept leaks identically on 1.1.35.

Summary

buildWSLegacyExecutor keeps a single closure-scoped object, executorConnectionParams, for the lifetime of the executor. Every execution that carries request.extensions.connectionParams merges those keys into that object with Object.assign, and the object is merged into the connection_init payload each time a new WebSocket opens. Nothing ever removes keys: cleanupWebsocket terminates the socket and nulls the handle but leaves executorConnectionParams intact, and a later request that simply omits a key skips the conditional update entirely.

The consumer-side shape is a shared executor that forwards per-user credentials. When one long-lived executor serves multiple principals — the schema-stitching, gateway, or mesh pattern where each ExecutionRequest supplies its own extensions.connectionParams — a request that omits the auth key is sent to the downstream server with the previous caller's Authorization/tenant values in its connection_init, so the downstream server authenticates the later caller as the earlier user.

Behaviour of the neighbouring state in the same file:

  • WebSocket handle (websocket) → reset on teardown in cleanupWebsocket, lines 78-88
  • Per-request connectionParams merge, present case → applied as documented, lines 93-101
  • executorConnectionParams closure object → never reset; survives socket teardown and is re-sent on the next connection, line 32 and line 54

Impact

A caller who supplies no credentials (or lower-privileged ones) can have its downstream GraphQL subscription executed under a previous user's retained token or tenant value, and can receive data that its own connection_init would not authorize. The credential itself is never disclosed to the attacker — it reaches the sink through closure storage, not because the attacker knows it — but the downstream authorization it represents is.

The new capability versus safe behaviour: without this bug, an anonymous request would open a connection whose connection_init contains only base options…

Record
GHSA-434m-5hcj-pxf3
CVSS 4.0
8.2 HighCVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-613
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
@graphql-tools/executor-legacy-ws
npm
through 1.1.35
1.1.36
@graphql-tools/executor-legacy-ws
npm
before 1.1.36
1.1.36

History

History
RecordedChangedSources
factsEUVD, NVD
referencesCVE List
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-118665 is a high vulnerability (CVSS 8.2) in @graphql-tools Executor-legacy-ws, published October 28, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.39%, the 33rd percentile. Fixed in @graphql-tools/executor-legacy-ws 1.1.36.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open