A stored XSS in jupyter-server's nbconvert endpoint allows any attacker who can place a malicious notebook in a shared location to achieve full kernel-level code execution on the victim's Jupyter instance. Because rendered HTML runs under the Jupyter origin with no CSP sandbox directive and HTMLExporter applies zero sanitization, a single page visit to /nbconvert/html/<path> exfiltrates the session token and grants the attacker unrestricted /api/* access — including spawning kernels and running arbitrary Python. With 1,874 downstream dependents and jupyter-server embedded in virtually every modern ML development environment (JupyterHub, SageMaker Studio, hosted notebook platforms), the blast radius extends to cloud credentials, model weights, and training data on any affected server. Patch to jupyter-server 2.20.0 immediately; for containerized builds, apply the two-line config override to NbconvertFileHandler and NbconvertPostHandler documented in the advisory.
What is the risk?
HIGH to CRITICAL. The vulnerability class — stored XSS with same-origin API authority — is well-understood and trivially weaponized; no novel exploit research is required. Exploitation requires only that an authenticated user opens a nbconvert HTML view of a malicious notebook, which is a routine collaborative workflow. In ML/AI environments this translates to kernel RCE on servers that typically hold cloud provider credentials in environment variables, API keys for LLM providers, GPU infrastructure access, and sensitive training datasets. The 20 prior CVEs in this package and an OpenSSF Scorecard of 5.8/10 signal a chronically underinvested security posture in a widely deployed dependency.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Jupyter | pip | — | No patch |
| Jupyter | pip | <= 2.19.0 | 2.20.0 |
| Jupyter Notebook | pip | — | No patch |
How severe is it?
What should I do?
6 steps-
Upgrade jupyter-server to >= 2.20.0 immediately — this is the definitive fix.
-
For containerized or read-only deployments where patching is impractical, apply the CSP sandbox workaround in jupyter_server_config.py: monkey-patch content_security_policy on both NbconvertFileHandler and NbconvertPostHandler to append '; sandbox allow-scripts' (exact code in the advisory).
-
Restrict the /nbconvert/ endpoint at the reverse proxy layer for public-facing instances to authenticated internal networks only.
-
Audit shared notebook repositories for suspicious display_data HTML payloads — grep for <script, onerror=, javascript:, and data: URI patterns in cell outputs.
-
Rotate Jupyter tokens and any cloud/LLM API credentials accessible from affected server environments.
-
Enforce per-user server isolation in JupyterHub to limit lateral blast radius.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-44727?
A stored XSS in jupyter-server's nbconvert endpoint allows any attacker who can place a malicious notebook in a shared location to achieve full kernel-level code execution on the victim's Jupyter instance. Because rendered HTML runs under the Jupyter origin with no CSP sandbox directive and HTMLExporter applies zero sanitization, a single page visit to /nbconvert/html/<path> exfiltrates the session token and grants the attacker unrestricted /api/* access — including spawning kernels and running arbitrary Python. With 1,874 downstream dependents and jupyter-server embedded in virtually every modern ML development environment (JupyterHub, SageMaker Studio, hosted notebook platforms), the blast radius extends to cloud credentials, model weights, and training data on any affected server. Patch to jupyter-server 2.20.0 immediately; for containerized builds, apply the two-line config override to NbconvertFileHandler and NbconvertPostHandler documented in the advisory.
Is CVE-2026-44727 actively exploited?
No confirmed active exploitation of CVE-2026-44727 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-44727?
1. Upgrade jupyter-server to >= 2.20.0 immediately — this is the definitive fix. 2. For containerized or read-only deployments where patching is impractical, apply the CSP sandbox workaround in jupyter_server_config.py: monkey-patch content_security_policy on both NbconvertFileHandler and NbconvertPostHandler to append '; sandbox allow-scripts' (exact code in the advisory). 3. Restrict the /nbconvert/ endpoint at the reverse proxy layer for public-facing instances to authenticated internal networks only. 4. Audit shared notebook repositories for suspicious display_data HTML payloads — grep for <script, onerror=, javascript:, and data: URI patterns in cell outputs. 5. Rotate Jupyter tokens and any cloud/LLM API credentials accessible from affected server environments. 6. Enforce per-user server isolation in JupyterHub to limit lateral blast radius.
What systems are affected by CVE-2026-44727?
This vulnerability affects the following AI/ML architecture patterns: ML training pipelines, AI development environments, MLOps platforms, Multi-user JupyterHub deployments, Data science workspaces.
What is the CVSS score for CVE-2026-44727?
No CVSS score has been assigned yet.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0011.003 Malicious Link AML.T0025 Exfiltration via Cyber Means AML.T0049 Exploit Public-Facing Application AML.T0050 Command and Scripting Interpreter AML.T0055 Unsecured Credentials AML.T0106 Exploitation for Credential Access Compliance Controls Affected
What are the technical details?
Original Advisory
The nbconvert HTTP handlers in jupyter_server render user-authored notebook HTML under the Jupyter origin without a sandbox directive in their `Content-Security-Policy`. Combined with `nbconvert.HTMLExporter`'s default non-sanitizing behavior, a notebook carrying an HTML payload in a display_data output triggers stored XSS with cookie access, full /api/* authority, and kernel RCE. ### Impact An authenticated victim who navigates to `/nbconvert/html/<path>` containing attacker-authored output can have their token exfiltrated to another domain because it is executed in the Jupyter origin. ### Patches Fixed in v2.20.0, commit [6cbee8d](https://github.com/jupyter-server/jupyter_server/commit/6cbee8d65e71abac851c4492fea987ad080580bd) ### Workarounds For deployments where editing the installed jupyter_server is impractical (containerized builds, read-only images), adding this to jupyter_server_config.py has the same effect as the patch above without touching source files: ``` import jupyter_server.nbconvert.handlers as _nb def _csp(self): return super(type(self), self).content_security_policy + "; sandbox allow-scripts" _nb.NbconvertFileHandler.content_security_policy = property(_csp) _nb.NbconvertPostHandler.content_security_policy = property(_csp) ```
Exploitation Scenario
An attacker with write access to a shared notebook repository — GitHub, an internal artifact store, or an S3 bucket used for ML experiment sharing — uploads a notebook with a crafted display_data output containing JavaScript that on render POSTs document.cookie and a fetch of /api/kernels to an attacker-controlled C2 server. A data scientist or ML engineer running jupyter-server <= 2.19.0 previews the notebook via /nbconvert/html/<path> as part of a code review or experiment handoff. The XSS payload fires in the Jupyter origin, the attacker receives the session token in real time, immediately authenticates to /api/kernels/execute, and runs arbitrary shell commands — extracting AWS_ACCESS_KEY_ID and OPENAI_API_KEY from the process environment and pivoting to the broader ML infrastructure.
Weaknesses (CWE)
CWE-1021 Improper Restriction of Rendered UI Layers or Frames
Primary
CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Primary
CWE-1021 — Improper Restriction of Rendered UI Layers or Frames: The web application does not restrict or incorrectly restricts frame objects or UI layers that belong to another application or domain.
- [Implementation] The use of X-Frame-Options allows developers of web content to restrict the usage of their application within the form of overlays, frames, or iFrames. The developer can indicate from which domains can frame the content. The concept of X-Frame-Options is well documented, but implementation of this protection mechanism is in development to cover gaps. There is a need for allowing frames from multiple domains.
- [Implementation] A developer can use a "frame-breaker" script in each page that should not be framed. This is very helpful for legacy browsers that do not support X-Frame-Options security feature previously mentioned. It is also important to note that this tactic has been circumvented or bypassed. Improper usage of frames can persist in the web application through nested frames. The "frame-breaking" script does not intuitively account for multiple nested frames that can be presented to the user.
Source: MITRE CWE corpus.
References
Timeline
Related Vulnerabilities
CVE-2023-25574 10.0 JupyterHub LTI13: JWT forgery enables full auth bypass
Same package: jupyter CVE-2026-44180 9.8 Jupyter Enterprise Gateway: root privilege bypass in Kubernetes
Same package: jupyter CVE-2026-42266 8.8 JupyterLab: Extension allow-list bypass enables privesc
Same package: jupyter CVE-2026-5422 8.1 jupyter-server: path traversal exposes sibling dir files
Same package: jupyter CVE-2025-30370 7.4 jupyterlab-git: command injection via malicious repo name
Same package: jupyter