Summary
On all platforms, JupyterLab Desktop versions prior to v4.6.2-1 exposed a getServerInfo IPC method to the renderer process that returned the full local Jupyter server URL - including the authentication token and port - regardless of whether the renderer had navigated away from the original JupyterLab page.
Combined with a missing target=_blank and noopener enforcement on links rendered by the MathJax HTML extension, an attacker could embed a crafted link in an untrusted notebook. A single click on that link navigates the JupyterLab Desktop window to an attacker-controlled site, which can then call getServerInfo to obtain the token. With the token, the attacker can use the Jupyter REST API to create a trusted notebook and execute arbitrary code on the victim's machine.
User interaction required: the victim must open a malicious notebook and click one link within it.
This issue affects all platforms (macOS, Windows, Linux). Users who had independently upgraded the JupyterLab version within their environment to ≥ 4.4.8 (which patches GHSA-vvfj-2jqx-52jm) are not affected, as the MathJax link enforcement in that release prevents Step 1 of the attack chain.
Note: CVE assignment pending - GitHub is experiencing a severe backlog in CVE assignment at the moment, please check back later if you need a CVE for this vulnerability.
Impact
An attacker who can deliver a malicious notebook to a victim - for example by sharing it as a file, via email, or through a code-sharing platform - can achieve remote code execution on the victim's machine if the victim opens the notebook and clicks one link within it.
Users are affected if all of the following conditions are true:
- they are running JupyterLab Desktop up to and including v4.2.5-1;
- the JupyterLab version in their environment is earlier than 4.4.8;
- they open the notebook in a local session (i.e. JupyterLab Desktop manages its own local Jupyter server, which is the default behaviour); and
- they click a link within the notebook.
By default, a link using the vulnerable component would render in a font different from normal links, however an attacker could include styles aimed at disguising the link in the notebook outputs.
Attack chain
The vulnerability is a combination of two weaknesses that are individually lower-severity but together enable one-click RCE:
- Step 1: Link escapes sandbox via MathJax HTML extension. Jupyter's notebook security model sanitizes HTML in untrusted notebooks and enforces
target=_blank and noopener on links, so that clicking a link opens an external site in a new window that has no access to the JupyterLab renderer context. However, links rendered by the MathJax HTML extension in the old JupyterLab versions (<4.4.8) bypassed this enforcement: the link lacked target=_blank and noopener, so clicking it navigated the existing JupyterLab Desktop window to the attacker's site rather than opening a new one.
- Step 2: Attacker's site calls
getServerInfo. After navigation, the attacker's page runs in the same Electron renderer window that previously held JupyterLab. The getServerInfo IPC method, exposed via the electronAPI preload bridge, remained accessible and returned the original local Jupyter server URL, including the randomised port and authentication token.
- Step 3: Token used to achieve RCE. With the token, the attacker calls the Jupyter REST API to create a new notebook, mark it as trusted, and navigate the victim to it. Viewing a trusted notebook is equivalent to executing code under Jupyter's security model, giving the attacker arbitrary code execution on the victim's machine.
Patches
Both weaknesses are fixed in v4.6.2-1:
- The
getServerInfo IPC method no longer returns the server URL after the renderer has navigated away from the JupyterLab origin.
- Links rendered by LaTeX typesetters now enforce
target=_blank and noopener in JupyterLab 4.4.8+
All users should upgrade to v4.6.2-1.
Workarounds
Users who cannot immediately upgrade should:
- Upgrade JupyterLab to ≥ 4.4.8 within their environment (
pip install --upgrade "jupyterlab>=4.4.8"). This patches the upstream MathJax link issue and breaks the attack chain at Step 1, even without upgrading JupyterLab Desktop itself.
- Avoid opening notebooks from untrusted sources in JupyterLab Desktop.
- Avoid clicking links inside notebooks whose provenance is not fully trusted.
Disabling the MathJax plugin is another workaround for users who cannot upgrade either of the versions:
jupyter labextension disable @jupyterlab/mathjax-extension
References
- GHSA-vvfj-2jqx-52jm - upstream JupyterLab advisory for missing
noopener on LaTeX typesetter links (patched in JupyterLab 4.4.8)
- 7f8f64a
Summary
On all platforms, JupyterLab Desktop versions prior to
v4.6.2-1exposed agetServerInfoIPC method to the renderer process that returned the full local Jupyter server URL - including the authentication token and port - regardless of whether the renderer had navigated away from the original JupyterLab page.Combined with a missing
target=_blankandnoopenerenforcement on links rendered by the MathJax HTML extension, an attacker could embed a crafted link in an untrusted notebook. A single click on that link navigates the JupyterLab Desktop window to an attacker-controlled site, which can then callgetServerInfoto obtain the token. With the token, the attacker can use the Jupyter REST API to create a trusted notebook and execute arbitrary code on the victim's machine.User interaction required: the victim must open a malicious notebook and click one link within it.
This issue affects all platforms (macOS, Windows, Linux). Users who had independently upgraded the JupyterLab version within their environment to ≥ 4.4.8 (which patches GHSA-vvfj-2jqx-52jm) are not affected, as the MathJax link enforcement in that release prevents Step 1 of the attack chain.
Impact
An attacker who can deliver a malicious notebook to a victim - for example by sharing it as a file, via email, or through a code-sharing platform - can achieve remote code execution on the victim's machine if the victim opens the notebook and clicks one link within it.
Users are affected if all of the following conditions are true:
Attack chain
The vulnerability is a combination of two weaknesses that are individually lower-severity but together enable one-click RCE:
target=_blankandnoopeneron links, so that clicking a link opens an external site in a new window that has no access to the JupyterLab renderer context. However, links rendered by the MathJax HTML extension in the old JupyterLab versions (<4.4.8) bypassed this enforcement: the link lackedtarget=_blankandnoopener, so clicking it navigated the existing JupyterLab Desktop window to the attacker's site rather than opening a new one.getServerInfo. After navigation, the attacker's page runs in the same Electron renderer window that previously held JupyterLab. ThegetServerInfoIPC method, exposed via theelectronAPIpreload bridge, remained accessible and returned the original local Jupyter server URL, including the randomised port and authentication token.Patches
Both weaknesses are fixed in v4.6.2-1:
getServerInfoIPC method no longer returns the server URL after the renderer has navigated away from the JupyterLab origin.target=_blankandnoopenerin JupyterLab 4.4.8+All users should upgrade to v4.6.2-1.
Workarounds
Users who cannot immediately upgrade should:
pip install --upgrade "jupyterlab>=4.4.8"). This patches the upstream MathJax link issue and breaks the attack chain at Step 1, even without upgrading JupyterLab Desktop itself.Disabling the MathJax plugin is another workaround for users who cannot upgrade either of the versions:
References
noopeneron LaTeX typesetter links (patched in JupyterLab 4.4.8)