VYPR
High severityOSV Advisory· Published Dec 17, 2025· Updated Feb 18, 2026

nbconvert has an uncontrolled search path that leads to unauthorized code execution on Windows

CVE-2025-53000

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.

PackageAffected versionsPatched versions
nbconvertPyPI
< 7.17.07.17.0

Affected products

1

Patches

1
c9ac1d104045

Fix 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

News mentions

0

No linked articles in our index yet.