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-H5V5-8746-G7MM

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

Amit Schendel
Amit Schendel
Senior Security Researcher

Jul 23, 2026·5 min read·4 visits

Executive Summary (TL;DR)

An authorization validation bypass and configuration mapping bug in JupyterLab's PluginManager allow authenticated users to circumvent extension locks and disable or enable arbitrary plugins through direct API requests.

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.

Vulnerability Overview

JupyterLab relies on an extensible plugin system where individual components control standard interface capabilities, administrative rules, and external network interactions.

Administrators in shared deployments, such as JupyterHub environments, often use lock policies to prevent standard users from disabling critical controls. These locked components may include auditing scripts, storage restrictions, download limits, or proxy features.

Although the frontend application visually disables the relevant interface buttons, the backend API endpoint (/lab/api/plugins) fails to robustly enforce authorization limits when accessed directly. Standard users can exploit this server-side gap to execute commands on locked extensions, violating administrative boundaries.

Root Cause Analysis

The root cause of this vulnerability involves two distinct server-side validation gaps in the JupyterLab backend infrastructure.

The first gap lies in how lock rules are evaluated inside jupyterlab/extensions/manager.py. In JupyterLab, plugin identifiers follow a hierarchical format consisting of the parent extension name and the child plugin name separated by a colon, such as <extension-name>:<plugin-identifier>.

When administrators apply a lock to an entire extension, only the parent extension name is stored in the lock registry. When a standard user sends a request to disable a specific plugin, the _find_locked method only checks if the exact, fully qualified child identifier is in the lock registry. Because it fails to parse and inspect the parent portion of the identifier, the server incorrectly determines that the plugin is unlocked.

The second gap stems from a configuration mismatch during the application startup configuration. Standard server initialization permits the option --LabApp.lock_all_plugins=True to globally lock all plugins. The launcher in jupyterlab/labapp.py passes this configuration parameter using the key "all_locked", but the PluginManager initialization logic expects the key "lock_all". This typographical error causes the global lock setting to be silently dropped during server initialization.

Code Diff Analysis

Examining the patch diff reveals the corrective validation and key-mapping changes across the affected files.

In jupyterlab/extensions/manager.py, the validation check was refactored to parse child plugin strings and check both the specific identifier and the parent extension identifier against the lock rules list.

# Vulnerable Implementation
def _find_locked(self, plugins_or_extensions: list[str]) -> frozenset[str]:
    for plugin in plugins_or_extensions:
        if ":" in plugin:
            # Only verifies the exact child identifier string
            if plugin in self.options.lock_rules:
                locked_subset.add(plugin)
 
# Patched Implementation
def _find_locked(self, plugins_or_extensions: list[str]) -> frozenset[str]:
    for plugin in plugins_or_extensions:
        if ":" in plugin:
            # Extracts parent extension name and checks both levels
            extension = plugin.split(":")[0]
            if plugin in self.options.lock_rules or extension in self.options.lock_rules:
                locked_subset.add(plugin)

Additionally, the option dictionary key in jupyterlab/labapp.py was aligned with the exact string that the backend validation engine expected to find.

# Vulnerable Mapping
ext_options={
    "lock_rules": lock_rules,
    "all_locked": self.lock_all_plugins,
}
 
# Patched Mapping
ext_options={
    "lock_rules": lock_rules,
    "lock_all": self.lock_all_plugins,
}

These modifications ensure that both targeted parent locks and global lock policies are correctly parsed, loaded, and evaluated by the server backend.

Exploit Mechanics

To exploit this vulnerability, an attacker must have authenticated access to a standard user account on the target JupyterLab server. Because the frontend interface prevents toggling via standard menus, the attacker bypasses the graphical console completely.

The attacker retrieves their active session cookie or authorization header and structures a manual HTTP POST request directed at /lab/api/plugins. This payload contains the parameters to disable the target security or auditing plugin.

POST /lab/api/plugins HTTP/1.1
Host: target-jupyterlab-server.com
Content-Type: application/json
Authorization: Token [user-api-token]
 
{
  "cmd": "disable",
  "plugin_name": "jupyterlab-hardening-extension:download-limiter"
}

Because the administrative lock was applied to the parent extension (jupyterlab-hardening-extension) and not the explicit child string, the backend verification function determines that the plugin is unlocked. The server executes the modification, disabling the designated control and returning a success status code to the client.

Security Impact Assessment

This vulnerability is highly significant in multi-user Jupyter environments such as JupyterHub configurations, where host controls depend on locked plugins.

By systematically disabling locked plugins, an attacker can bypass operational limitations, escape container restrictions, and avoid active monitoring controls. This effectively deactivates any local auditing tools or transfer limitations applied by administrative security frameworks.

However, this vulnerability does not directly permit initial remote code execution or privilege escalation on the underlying host operating system. The attacker must possess authenticated login credentials to interact with the API, making it an internal post-authentication policy evasion vector.

Mitigation and Remediation

The standard and recommended remediation path is to upgrade JupyterLab to the officially patched versions.

Administrators using the 4.5.x release line should update to version 4.5.10 or higher, and those on the 4.6.x line should upgrade to version 4.6.2 or higher. Any downstream wrapper distributions should have their requirements updated to reflect these dependency parameters.

If patching is not immediately feasible, administrators can temporarily mitigate the vulnerability by changing their deployment policies. Rather than applying locks at the parent extension level, lock files must register each child plugin identifier individually.

jupyter labextension lock <extension-name>:<child-plugin-id-1>
jupyter labextension lock <extension-name>:<child-plugin-id-2>

This explicit locking ensures that direct API queries will match the exact strings in the lock list, neutralizing the parent parsing bypass.

Official Patches

JupyterLabPull Request 19184
JupyterLabPull Request 19185
JupyterLabPull Request 19186

Fix Analysis (2)

Technical Appendix

CVSS Score
6.0/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N

Affected Systems

jupyterlab

Affected Versions Detail

Product
Affected Versions
Fixed Version
jupyterlab
Project Jupyter
>= 4.1.0, <= 4.5.94.5.10
jupyterlab
Project Jupyter
>= 4.6.0, <= 4.6.14.6.2
AttributeDetail
CWE IDCWE-602, CWE-863
Attack VectorNetwork
CVSS6.0
ImpactHigh Integrity, Low Confidentiality
Exploit StatusPoC Available
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1562.001Impair Defenses: Disable or Modify Tools
Defense Evasion
T1548Abuse Elevation Control Mechanism
Privilege Escalation
CWE-602
Client-Side Enforcement of Server-Side Security

The application's UI visually disables/locks the interface components to prevent users from toggling extension states, but the backend fails to properly validate and reject direct API state-change requests from the client.

References & Sources

  • [1]Official GitHub Advisory
  • [2]Security Advisory Detail Page
  • [3]Core Plugin Identifiers
  • [4]Extension Manager Configuration

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

•about 1 hour ago•GHSA-WHVH-WF3X-G77J
0.0

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

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.

Amit Schendel
Amit Schendel
0 views•6 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 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
•about 6 hours ago•GHSA-9CMH-XCQM-5HQR
5.8

GHSA-9cmh-xcqm-5hqr: Cross-Tenant Module-Cache Poisoning in n8n JS Task Runner

A module-cache poisoning vulnerability exists in the n8n JavaScript task runner. In multi-tenant or multi-user n8n deployments, custom code executed inside Code nodes shares a single Node.js process and memory space. If custom module loading is enabled via configuration, an authorized user can dynamically patch (monkey-patch) globally cached modules. Subsequent executions of workflows by other tenants or users that load the same module will receive the poisoned reference, resulting in cross-tenant data exposure, credential hijacking, or integrity compromise.

Alon Barad
Alon Barad
6 views•6 min read