nbconvert has an uncontrolled search path that leads to unauthorized code execution on Windows
Description
The nbconvert tool, jupyter nbconvert, converts Jupyter notebooks to various other formats via Jinja templates. Versions of nbconvert up to and including 7.16.6 on Windows have a vulnerability in which converting a notebook containing SVG output to a PDF results in unauthorized code execution. Specifically, a third party can create a inkscape.bat file that defines a Windows batch script, capable of arbitrary code execution. When a user runs jupyter nbconvert --to pdf on a notebook containing SVG output to a PDF on a Windows platform from this directory, the inkscape.bat file is run unexpectedly. This issue has been patched in version 7.17.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
nbconvertPyPI | < 7.17.0 | 7.17.0 |
Affected products
1Patches
1c9ac1d104045Fix CVE-2025-53000: Secure Inkscape Windows path (registry first + block CWD) (#2261)
1 file changed · +47 −11
nbconvert/preprocessors/svg2pdf.py+47 −11 modified@@ -9,6 +9,8 @@ import os import subprocess import sys +import warnings +from pathlib import Path from shutil import which from tempfile import TemporaryDirectory @@ -101,26 +103,60 @@ def _command_default(self): @default("inkscape") def _inkscape_default(self): + # Windows: Secure registry lookup FIRST (CVE-2025-53000 fix) + if sys.platform == "win32": + wr_handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) + try: + rkey = winreg.OpenKey(wr_handle, r"SOFTWARE\Classes\inkscape.svg\DefaultIcon") + inkscape_full = winreg.QueryValueEx(rkey, "")[0].split(",")[0] # Fix: remove ",0" + if os.path.isfile(inkscape_full): + return inkscape_full + except (FileNotFoundError, OSError, IndexError): + pass # Safe fallback + + # Block CWD in PATH search (CVE-2025-53000) + os.environ["NODEFAULTCURRENTDIRECTORYINEXEPATH"] = "1" + inkscape_path = which("inkscape") + + # Extra safety for Python < 3.12 on Windows: + # If which() resolved to a path in CWD even though CWD is not on PATH, + # warn and treat as "not found". + if sys.platform == "win32" and inkscape_path and sys.version_info < (3, 12): + try: + cwd = Path.cwd().resolve() + in_cwd = Path(inkscape_path).resolve().parent == cwd + cwd_on_path = cwd in { + Path(p).resolve() for p in os.environ.get("PATH", os.defpath).split(os.pathsep) + } + + if in_cwd and not cwd_on_path: + warnings.warn( + "shutil.which('inkscape') resolved to an executable in the current " + "working directory even though CWD is not on PATH. Ignoring this " + "result for security reasons (CVE-2025-53000).", + RuntimeWarning, + stacklevel=2, + ) + inkscape_path = None + except Exception: + # If detection fails for any reason, prefer safety: ignore CWD result + inkscape_path = None + if inkscape_path is not None: return inkscape_path + + # macOS: EXACT original order preserved if sys.platform == "darwin": if os.path.isfile(INKSCAPE_APP_v1): return INKSCAPE_APP_v1 # Order is important. If INKSCAPE_APP exists, prefer it over # the executable in the MacOS directory. if os.path.isfile(INKSCAPE_APP): return INKSCAPE_APP - if sys.platform == "win32": - wr_handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - try: - rkey = winreg.OpenKey(wr_handle, "SOFTWARE\\Classes\\inkscape.svg\\DefaultIcon") - inkscape = winreg.QueryValueEx(rkey, "")[0] - except FileNotFoundError: - msg = "Inkscape executable not found" - raise FileNotFoundError(msg) from None - return inkscape - return "inkscape" + + msg = "Inkscape executable not found in safe paths" + raise FileNotFoundError(msg) def convert_figure(self, data_format, data): """ @@ -144,7 +180,7 @@ def convert_figure(self, data_format, data): else: # For backwards compatibility with specifying strings # Okay-ish, since the string is trusted - full_cmd = self.command.format(*template_vars) + full_cmd = self.command.format(**template_vars) subprocess.call(full_cmd, shell=isinstance(full_cmd, str)) # noqa: S603 # Read output from drive
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-xm59-rqc7-hhvfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-53000ghsaADVISORY
- github.com/jupyter/nbconvert/blob/4f61702f5c7524d8a3c4ac0d5fc33a6ac2fa36a7/nbconvert/preprocessors/svg2pdf.pyghsax_refsource_MISCWEB
- github.com/jupyter/nbconvert/commit/c9ac1d1040459ed1ff9eb34e9918ce5a87cf9d71ghsax_refsource_MISCWEB
- github.com/jupyter/nbconvert/issues/2258ghsax_refsource_MISCWEB
- github.com/jupyter/nbconvert/releases/tag/v7.17.0ghsax_refsource_MISCWEB
- github.com/jupyter/nbconvert/security/advisories/GHSA-xm59-rqc7-hhvfghsax_refsource_CONFIRMWEB
- www.imperva.com/blog/code-execution-in-jupyter-notebook-exportsghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.