GHSA-354V-3Q48-CV69
Vulnerability from github – Published: 2026-10-22 15:46 – Updated: 2026-10-22 15:46Summary
Jupyter Server's gateway WebSocket handler checks that a user is authenticated, but it does not ask the configured Authorizer whether that user may execute kernels.
In Jupyter Server 2.0.0 through 2.5.0, enabling GatewayClient.url automatically replaced the normal kernel channel handler with this gateway-specific handler. An authenticated user who is denied the execute action on the kernels resource can therefore still open a kernel channel and send messages to the upstream kernel.
Details
The normal handler performs the expected authorization check before creating the WebSocket connection:
https://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/services/kernels/websocket.py#L39-L47
The gateway handler only checks current_user and then opens the upstream channel. It never calls authorizer.is_authorized(...):
https://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/gateway/handlers.py#L49-L75 https://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/gateway/handlers.py#L87-L98
Gateway mode selected that handler automatically by replacing handlers with matching routes:
https://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/serverapp.py#L437-L446
PR #1261 stopped replacing the normal handler and routed gateway traffic through GatewayWebSocketConnection instead. This appears to have fixed the default gateway configuration in 2.6.0, although the deprecated handler is still present in current releases and can still be registered directly.
https://github.com/jupyter-server/jupyter_server/pull/1261
Code-level validation
- Configure a custom Authorizer that returns false for
executeonkernelsfor a regular authenticated user. - Configure
GatewayClient.urlon Jupyter Server 2.0.0-2.5.0. - The normal
KernelWebsocketHandlerwould reject that user with 403 inpre_get. - Gateway mode replaces it with
WebSocketChannelsHandler. Itsauthenticatemethod only rejects anonymous users, andgetproceeds to the upstream gateway without an authorization decision.
Impact
This is a missing authorization check, not an authentication bypass. It matters in deployments that use a restrictive custom Authorizer and Jupyter Gateway/Enterprise Gateway. A read-only or otherwise limited authenticated user can cross the intended authorization boundary and obtain kernel execution, with access to data and credentials available to that kernel.
Affected versions
- Default gateway configuration: 2.0.0 through 2.5.0
- 2.6.0 and later: the default path uses the authorized standard handler, but manually registering the deprecated
jupyter_server.gateway.handlersmodule still exposes the old behavior.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "jupyter-server"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0"
},
{
"fixed": "2.6.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-114135"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-22T15:46:31Z",
"nvd_published_at": "2026-10-21T20:17:25Z",
"severity": "HIGH"
},
"details": "### Summary\n\nJupyter Server\u0027s gateway WebSocket handler checks that a user is authenticated, but it does not ask the configured Authorizer whether that user may execute kernels.\n\nIn Jupyter Server 2.0.0 through 2.5.0, enabling GatewayClient.url automatically replaced the normal kernel channel handler with this gateway-specific handler. An authenticated user who is denied the `execute` action on the `kernels` resource can therefore still open a kernel channel and send messages to the upstream kernel.\n\n### Details\n\nThe normal handler performs the expected authorization check before creating the WebSocket connection:\n\nhttps://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/services/kernels/websocket.py#L39-L47\n\nThe gateway handler only checks `current_user` and then opens the upstream channel. It never calls `authorizer.is_authorized(...)`:\n\nhttps://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/gateway/handlers.py#L49-L75\nhttps://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/gateway/handlers.py#L87-L98\n\nGateway mode selected that handler automatically by replacing handlers with matching routes:\n\nhttps://github.com/jupyter-server/jupyter_server/blob/v2.5.0/jupyter_server/serverapp.py#L437-L446\n\nPR #1261 stopped replacing the normal handler and routed gateway traffic through `GatewayWebSocketConnection` instead. This appears to have fixed the default gateway configuration in 2.6.0, although the deprecated handler is still present in current releases and can still be registered directly.\n\nhttps://github.com/jupyter-server/jupyter_server/pull/1261\n\n### Code-level validation\n\n1. Configure a custom Authorizer that returns false for `execute` on `kernels` for a regular authenticated user.\n2. Configure `GatewayClient.url` on Jupyter Server 2.0.0-2.5.0.\n3. The normal `KernelWebsocketHandler` would reject that user with 403 in `pre_get`.\n4. Gateway mode replaces it with `WebSocketChannelsHandler`. Its `authenticate` method only rejects anonymous users, and `get` proceeds to the upstream gateway without an authorization decision.\n\n### Impact\n\nThis is a missing authorization check, not an authentication bypass. It matters in deployments that use a restrictive custom Authorizer and Jupyter Gateway/Enterprise Gateway. A read-only or otherwise limited authenticated user can cross the intended authorization boundary and obtain kernel execution, with access to data and credentials available to that kernel.\n\n### Affected versions\n\n- Default gateway configuration: 2.0.0 through 2.5.0\n- 2.6.0 and later: the default path uses the authorized standard handler, but manually registering the deprecated `jupyter_server.gateway.handlers` module still exposes the old behavior.",
"id": "GHSA-354v-3q48-cv69",
"modified": "2026-10-22T15:46:31Z",
"published": "2026-10-22T15:46:31Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jupyter-server/jupyter_server/security/advisories/GHSA-354v-3q48-cv69"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-114135"
},
{
"type": "WEB",
"url": "https://github.com/jupyter-server/jupyter_server/pull/1261"
},
{
"type": "WEB",
"url": "https://github.com/jupyter-server/jupyter_server/commit/35ffe5d435682128da16dc144a8e9e9f8fa85dd8"
},
{
"type": "PACKAGE",
"url": "https://github.com/jupyter-server/jupyter_server"
},
{
"type": "WEB",
"url": "https://github.com/jupyter-server/jupyter_server/releases/tag/v2.6.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Jupyter Server: Gateway WebSocket handler bypasses kernel execute authorization"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.