CVE-2026-39377: Arbitrary File Write via Path Traversal in Jupyter nbconvert
Vulnerability ID: CVE-2026-39377
CVSS Score: 6.5
Published: 2026-04-21
Jupyter nbconvert versions 6.5 through 7.17.0 contain a path traversal vulnerability resulting in arbitrary file write capabilities. The ExtractAttachmentsPreprocessor fails to sanitize filenames extracted from notebook cell attachments before constructing output paths. Processing a maliciously crafted Jupyter notebook allows an attacker to write files outside the intended output directory, potentially leading to remote code execution.
TL;DR
A path traversal vulnerability in Jupyter nbconvert allows attackers to write arbitrary files to the filesystem when a victim converts a maliciously crafted notebook. The flaw is patched in version 7.17.1.
⚠️ Exploit Status: POC
Technical Details
- CWE ID: CWE-22 / CWE-73
- Attack Vector: Network (Requires User Interaction)
- Impact: Arbitrary File Write / Potential RCE
- CVSS v3.1: 6.5 (Medium)
- EPSS Score: 0.00031 (8.97th percentile)
- Exploit Status: Proof of Concept (PoC)
- CISA KEV: Not Listed
Affected Systems
- Jupyter Notebook Environments
- Automated CI/CD pipelines processing .ipynb files
- Web applications generating document exports from user-supplied notebooks
-
nbconvert: >= 6.5, < 7.17.1 (Fixed in:
7.17.1)
Code Analysis
Commit: ba5e5cd
Primary patch for ExtractAttachmentsPreprocessor using os.path.basename()
@@ -82,6 +82,22 @@ def preprocess_cell(self, cell, resources, index):
for fname in cell.attachments:
self.log.debug("Encountered attachment %s", fname)
+ # Sanitize: use only the basename to prevent path traversal
+ safe_fname = os.path.basename(fname)
+ if not safe_fname:
+ self.log.warning("Attachment filename '%s' is invalid, skipping", fname)
+ continue
+ if safe_fname != fname:
+ self.log.warning("Attachment filename '%s' contained path components, using basename '%s'", fname, safe_fname)
+
# ...
- new_filename = os.path.join(self.path_name, fname)
+ new_filename = os.path.join(self.path_name, safe_fname)
Commit: 0e6b8cc
Secondary patch for markdown_mistune image embedding using os.path.abspath()
@@ -437,6 +437,11 @@ def _src_to_base64(self, src: str) -> Optional[str]:
src_path = os.path.join(self.path, src)
+ resolved = os.path.abspath(src_path)
+ allowed_base = os.path.abspath(self.path)
+ if not resolved.startswith(allowed_base + os.sep) and resolved != allowed_base:
+ return None
Mitigation Strategies
- Upgrade nbconvert to a patched version
- Disable ExtractAttachmentsPreprocessor for untrusted inputs
- Set embed_images=False during HTML conversion
- Run nbconvert in an isolated container environment
Remediation Steps:
- Verify current nbconvert version using pip list or conda list
- Update nbconvert to version 7.17.1 or higher via package manager
- Review filesystem logs for unexpected file modifications outside standard output directories
- Monitor application logs for path traversal warnings originating from nbconvert
References
- GHSA-4c99-qj7h-p3vg Security Advisory
- NVD Record for CVE-2026-39377
- Primary Patch Commit
- Secondary Patch Commit
Read the full report for CVE-2026-39377 on our website for more details including interactive diagrams and full exploit analysis.
Top comments (0)