CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-WHVH-WF3X-G77J

GHSA-WHVH-WF3X-G77J: Improper Access Control and Listing Bypass in JupyterLab Extension Manager

Amit Schendel
Amit Schendel
Senior Security Researcher

Jul 23, 2026·6 min read·1 visit

Executive Summary (TL;DR)

JupyterLab's extension installation interface failed to await its blocklist checking coroutine, causing it to evaluate to True and bypass extension restrictions for direct API callers. The issue was compounded by a lack of package name normalization (PEP 503) during comparison.

An improper access control vulnerability in JupyterLab allows programmatic installation of blocked or non-allowed extensions. The vulnerability is caused by a missing await keyword when invoking the asynchronous checking method, leading Python to evaluate the returned coroutine object as truthy. Furthermore, the check lacks proper canonicalization of package names, enabling an attacker to bypass blocklists using casing or character variants.

Vulnerability Overview

JupyterLab incorporates an extension manager that permits administrators and users to install additional packages from the Python Package Index (PyPI) to extend frontend and backend capabilities. To ensure secure operation in multi-tenant or enterprise environments, JupyterLab provides configuration settings to define allowlists or blocklists. These lists restrict the specific extension packages that users are permitted to deploy to the server instance.

The vulnerability tracked as GHSA-WHVH-WF3X-G77J represents a complete breakdown in this access control boundary. In the default PyPIExtensionManager, the validation layer designed to intercept and prevent prohibited installation calls does not execute properly within the install() function. Instead, Python's runtime behavior causes the code to bypass the validation conditional check entirely.

This vulnerability is categorized under CWE-284 (Improper Access Control) and CWE-636 (Not Failing Securely). The exposure is highly dependent on deployment configuration. While standard out-of-the-box installations filter requests at the HTTP routing tier, custom downstream integrations or direct programmatic calls to the manager APIs are left completely unprotected by this failure.

Root Cause Analysis

The fundamental flaw in jupyterlab/extensions/pypi.py centers on the improper execution of asynchronous code. The method responsible for installing packages, PyPIExtensionManager.install(), is defined as a standard Python asynchronous function (async def). Within its body, it evaluates authorization by invoking self.is_install_allowed(name, version).

Because is_install_allowed is itself an asynchronous function, executing it simply as a function call—without prefixing it with the await keyword—returns a Python coroutine object rather than its resolved boolean result. In Python, any object context evaluated by a conditional check defaults to a truthy value unless the object explicitly implements a false evaluation, which coroutine objects do not. Therefore, the conditional expression if not self.is_install_allowed(name, version) is evaluated as if not <coroutine_object>, resolving to if not True, which becomes False and bypasses the error-handling block.

Additionally, a secondary vulnerability exists due to a lack of canonicalization. When looking up package names in the allowlist or blocklist cache, JupyterLab used an identity-preserving normalizer that returned the raw input. Under PEP 503 rules, PyPI treats characters like hyphens, dots, and underscores as equivalent. An administrator blocking jupyterlab-git could have their security policy bypassed if a user requested installation of JupyterLab_Git because the server compared raw strings but the downstream installer (pip) fetched and executed the blocked package anyway.

Code Analysis and Architectural Flow

An analysis of the vulnerable source code in jupyterlab/extensions/pypi.py highlights the logical error. The validation block was implemented as follows:

# Vulnerable implementation in jupyterlab/extensions/pypi.py
async def install(self, name: str, version: Optional[str] = None) -> ActionResult:
    # ... configuration loading ...
    if not self.is_install_allowed(name, version):
        # This block is unreachable because the coroutine object is truthy
        return ActionResult(status="error", message="install is not allowed")

To resolve this issue, the patch inserts the missing await operator to ensure the coroutine resolves to a boolean before negation. It also replaces the basic _normalize_name placeholder method with proper PEP 503 package canonicalization using the packaging.utils.canonicalize_name utility:

# Patched implementation showing corrected await and canonicalization
@override
async def install(self, name: str, version: Optional[str] = None) -> ActionResult:
    # ... configuration loading ...
    if not await self.is_install_allowed(name, version):
        # The await keyword forces execution and returns the true boolean value
        return ActionResult(status="error", message="install is not allowed")

Attack Scenario Analysis

For this vulnerability to be exploitable, specific conditions must align. The stock JupyterLab application employs an HTTP endpoint handler that runs its own properly-awaited checks before initiating the installation process. Thus, an attacker interacting solely with an unmodified stock JupyterLab HTTP REST API cannot exploit this flaw directly.

However, in enterprise environments, JupyterLab is commonly customized with downstream extensions, multi-tenant launching frameworks, or tailored administration consoles. If these custom implementations invoke PyPIExtensionManager.install() programmatically and rely on the manager to self-enforce the configure policy, the bypass is active. An attacker who has low-privileged user-level access to these custom components can request a restricted package name.

To execute a canonicalization bypass, the attacker targets the blocklist dictionary. If an administrator blocks restricted-extension, the attacker requests Restricted_Extension. Due to the lack of proper canonicalization, the string check fails to match the blocklist entry. The execution proceeds to pip, which normalizes the name to restricted-extension and installs the package, successfully achieving privilege escalation or execution of prohibited capabilities on the server hosting the JupyterLab instance.

Impact Assessment & Threat Context

The overall impact of this vulnerability is categorized as Low, resulting in a CVSS v3.1 score of 0.0. This score reflects the default state of JupyterLab, where the primary HTTP endpoints are secured by independent pre-checks. The vulnerability represents a loss of defense-in-depth, as the internal API does not fail securely when accessed directly by downstream software.

The real-world impact rises in scenarios where third-party JupyterLab integrations are deployed. In these scenarios, the vulnerability permits bypass of administrative controls. This allows unauthorized package installations on the host system, which could lead to remote code execution in the context of the JupyterLab server process.

No exploitation in the wild or weaponized proof-of-concept material has been observed. Additionally, the vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, nor is there any evidence of its use in active ransomware campaigns.

Mitigation & Remediation

The primary remediation strategy is upgrading the underlying jupyterlab installation to a patched version. Security patches have been backported to both the 4.5.x and 4.6.x release streams. Administrators should transition environments to version 4.5.10 or 4.6.2 respectively.

If patching is not immediately feasible, administrators can apply workarounds. The risk can be mitigated by disabling the default extension manager UI or changing its operational state to read-only mode. This configuration removes the installation code path entirely, preventing potential misuse by users.

To enforce the read-only mode, launch the server with the explicit CLI argument --LabApp.extension_manager=readonly. Alternatively, add the configuration line c.LabApp.extension_manager = 'readonly' to the system-wide jupyter_server_config.py file. This prevents any PyPI installation actions from executing on the server.

Official Patches

JupyterLab GitHub AdvisoryOfficial Security Advisory for JupyterLab Extension Manager policy bypass

Fix Analysis (2)

Technical Appendix

CVSS Score
0.0/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:N

Affected Systems

JupyterLab server installations utilizing PyPIExtensionManager under non-default integrations

Affected Versions Detail

Product
Affected Versions
Fixed Version
jupyterlab
Jupyter
>= 4.6.0, <= 4.6.14.6.2
jupyterlab
Jupyter
<= 4.5.94.5.10
AttributeDetail
CWE IDCWE-636 (Not Failing Securely / 'Failing Open')
Attack VectorNetwork
CVSS v3.1 Score0.0 (Low/None due to default application routing context)
Exploit MaturityNone (No public exploits or Proof of Concepts available)
CISA KEV StatusNot Listed
Affected Componentsjupyterlab/extensions/pypi.py and jupyterlab/extensions/manager.py

MITRE ATT&CK Mapping

T1548Abuse Elevation Control Mechanism
Privilege Escalation
T1195Supply Chain Compromise
Initial Access
CWE-636
Not Failing Securely ('Failing Open')

The product does not fail securely when an operational error or structural bypass occurs, leading to a breakdown in access control constraints.

References & Sources

  • [1]JupyterLab Security Advisory
  • [2]Pull Request 19184: Patch for JupyterLab Master
  • [3]Pull Request 19185: Patch for JupyterLab 4.6.x
  • [4]Pull Request 19186: Patch for JupyterLab 4.5.x

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•10 minutes ago•CVE-2026-8384
5.3

CVE-2026-8384: URI Path Parameter Parser State-Desynchronization Path Traversal in Eclipse Jetty

A path traversal vulnerability exists in Eclipse Jetty due to a state-desynchronization defect in the URI parsing state machine inside URIUtil.java. This defect allows unauthenticated remote attackers to bypass path-based security constraints enforced by downstream filters, application gateways, or authorization modules by crafting URIs with path parameter delimiters and parent directory traversal sequences.

Amit Schendel
Amit Schendel
0 views•7 min read
•about 1 hour ago•CVE-2026-42980
7.8

CVE-2026-42980: Windows Kernel Local Privilege Escalation via WMI Integer Underflow

An unsigned 32-bit integer underflow vulnerability in the Windows Management Instrumentation (WMI) serialization subsystem of ntoskrnl.exe allows local authenticated users with low privileges to corrupt adjacent kernel pool allocations, execute arbitrary kernel-mode read and write operations, and perform a Token Swap attack to escalate their privileges to NT AUTHORITY\SYSTEM.

Amit Schendel
Amit Schendel
3 views•7 min read
•about 2 hours ago•GHSA-H5V5-8746-G7MM
6.0

GHSA-H5V5-8746-G7MM: JupyterLab PluginManager Lock-Rule Enforcement Bypass

JupyterLab's PluginManager contains an authorization bypass vulnerability allowing authenticated users to modify the state of locked extensions or plugins. Although the frontend user interface visually locks and disables toggle components for administrative configurations, the backend API fails to perform robust validation. Standard users can craft direct HTTP API requests to modify plugin states, completely bypassing administrative restrictions.

Amit Schendel
Amit Schendel
4 views•5 min read
•about 3 hours ago•GHSA-89VP-JRXV-24W8
6.1

GHSA-89VP-JRXV-24W8: Extension Manager Blocklist Canonicalization Bypass in JupyterLab

GHSA-89VP-JRXV-24W8 is a security bypass vulnerability in the JupyterLab Extension Manager. Authenticated users can install unauthorized or blocklisted extension packages from PyPI. This bypass occurs due to improper canonicalization of package names and the incorrect synchronous invocation of an asynchronous permission-checking method.

Amit Schendel
Amit Schendel
9 views•5 min read
•about 4 hours ago•GHSA-GX64-GJ6P-PC4C
8.2

GHSA-GX64-GJ6P-PC4C: Stored Cross-Site Scripting in JupyterLab Image Viewer

A stored Cross-Site Scripting (XSS) vulnerability exists in JupyterLab's Image Viewer component when processing Scalable Vector Graphics (SVG) images. Due to the lingering lifecycle of generated object URLs and the inheritance of the application origin by client-side Blobs, an attacker can execute arbitrary JavaScript within the victim's active session. This execution occurs when a user views an SVG file in the JupyterLab image viewer, right-clicks the image, and selects 'Open image in new tab'.

Amit Schendel
Amit Schendel
6 views•7 min read
•about 5 hours ago•GHSA-PPPJ-HQ3G-57PJ
8.6

GHSA-pppj-hq3g-57pj: DOM-based Cross-Site Scripting (XSS) via Malicious Settings Override in JupyterLab

JupyterLab versions 4.5.x and 4.6.x prior to 4.5.10 and 4.6.2 are vulnerable to a DOM-based Cross-Site Scripting (XSS) vulnerability. An attacker can craft a malicious overrides.json file that executes arbitrary JavaScript inside the victim's browser session. This can occur either automatically if the file is pre-planted on a multi-tenant filesystem, or via user interaction when importing settings.

Alon Barad
Alon Barad
4 views•5 min read