Apr 22, 2026·7 min read·3 visits
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.
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.
The nbconvert utility functions as a core component of the Project Jupyter ecosystem, translating .ipynb notebook files into static formats such as HTML, Markdown, and PDF. The conversion process relies on Jinja templates and preprocessors to parse and format the notebook data. A key feature of the Jupyter notebook format is the ability to embed files directly within the document using cell attachments, which store data inline as base64-encoded strings.
Versions 6.5 through 7.17.0 of nbconvert contain an arbitrary file write vulnerability due to improper path sanitization. The vulnerability specifically resides within the ExtractAttachmentsPreprocessor component, which handles the extraction of these embedded files to the local filesystem during the conversion process. The preprocessor extracts the filename from the notebook metadata but fails to validate or neutralize path traversal sequences within the string.
The vulnerability enables an attacker to supply a crafted .ipynb file that writes data to arbitrary filesystem locations when processed by a victim. The attacker exercises complete control over both the destination path and the contents of the written file. This constitutes a severe integrity violation of the host operating system, classified under CWE-22 (Improper Limitation of a Pathname to a Restricted Directory).
Additionally, the developers identified a secondary manifestation of the traversal vulnerability within the image embedding filter (markdown_mistune.py). When the embed_images=True configuration flag is utilized during HTML conversion, the filter lacks boundary enforcement for local file inclusion. This secondary vector facilitates local file exfiltration by embedding arbitrary system files into the generated output document.
The root cause of this vulnerability stems from passing unsanitized, user-controlled input directly into insecure path construction functions. Within a Jupyter notebook file, cell attachments are structured as a JSON dictionary inside the cell metadata. The keys of this dictionary dictate the filenames for the attachments, while the values contain the corresponding encoded file data.
The ExtractAttachmentsPreprocessor class implements a loop that iterates over these dictionary keys to extract the attachment contents. During this process, the preprocessor passes the raw dictionary key directly to Python's os.path.join() function as the filename parameter. The software implicitly trusts the attachment key to be a simple, safe filename string.
Python's os.path.join() exhibits specific operational behavior when handling absolute paths or path traversal sequences. If the appended path component contains standard traversal characters (../), the resulting concatenated path resolves outside the intended base directory. Furthermore, if the appended component is an absolute path string, os.path.join() discards the base directory entirely and returns the absolute path.
The primary vulnerability in nbconvert/preprocessors/extractattachments.py was resolved in commit ba5e5cdd737704388251fa55fa9e58f5752fa39d. The original, vulnerable implementation accepted the fname variable directly from the cell.attachments dictionary and appended it to the self.path_name variable.
# Vulnerable implementation in nbconvert < 7.17.1
# FilesWriter wants path to be in attachment filename here
new_filename = os.path.join(self.path_name, fname)
resources[self.resources_item_key][new_filename] = decodedThe patch mitigates the path traversal by filtering the fname variable through os.path.basename(). This function systematically strips all preceding directory components from the string, ensuring that only the final, terminating filename remains. The patch implementation also introduces validation checks to log warnings and skip processing if the resulting basename is empty or altered.
# Patched implementation in nbconvert 7.17.1
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, safe_fname)The secondary fix in nbconvert/filters/markdown_mistune.py (commit 0e6b8ccabf2aca6c18fac8c574f22b7155f441fb) implements a rigid path containment check. The developers utilized os.path.abspath() to resolve both the target file path and the allowed base directory. The logic then verifies that the fully resolved target path string begins with the allowed base directory string, effectively neutralizing traversal attempts.
Exploitation of CVE-2026-39377 requires the attacker to construct a valid .ipynb document containing a maliciously crafted cell attachment. The attacker manipulates the JSON structure of the file, modifying a cell's metadata dictionary. The attacker sets the attachment key to a string containing path traversal sequences or an absolute filesystem path, and populates the corresponding value with base64-encoded payload data.
The attacker must then deliver the modified notebook file to a target system. The execution phase triggers when the victim or an automated process invokes nbconvert against the malicious file. This interaction can occur directly via the command-line interface or indirectly through web applications that utilize nbconvert as a backend processing service.
The following JSON snippet demonstrates the internal structure of a malicious .ipynb payload. In this example, the attacker targets the SSH configuration directory.
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
],
"attachments": {
"../../../../../../home/user/.ssh/authorized_keys": {
"text/plain": "c3NoLXJzYSBBQUFB...[base64 encoded ssh public key]..."
}
}
}Upon processing this file, nbconvert parses the JSON, extracts the malicious key, and decodes the payload. The software then writes the decoded payload to the specified absolute path. The file write operation executes under the user and group privileges of the process running nbconvert.
The primary consequence of this vulnerability is arbitrary file write on the host filesystem. An attacker controls both the absolute destination path and the exact byte contents of the resulting file. This capability provides the attacker with the means to overwrite sensitive configuration parameters, modify executing application code, or deposit arbitrary scripts onto the target host.
Arbitrary file write vulnerabilities in command-line utilities frequently escalate to complete system compromise via remote code execution. Attackers achieve execution by targeting specific operating system loading mechanisms. Common escalation vectors include writing executable shell scripts to /etc/cron.d/, modifying user shell profiles like .bashrc, or appending cryptographic keys to ~/.ssh/authorized_keys to establish persistent remote access.
The secondary vulnerability located in the image embedding filter introduces an arbitrary file read capability to the attack surface. If the victim environment utilizes the embed_images=True configuration flag, an attacker can specify absolute paths to local system files within the markdown image tags. The nbconvert process subsequently reads these files, encodes them, and embeds the sensitive system data into the resulting output document.
The CVSS v3.1 score of 6.5 categorizes this flaw as Medium severity. The score structure reflects the necessity of user interaction, as the attack strictly depends on a user actively processing the malicious file with the vulnerable tool. The associated EPSS score is 0.00031, indicating that widespread automated exploitation is highly improbable.
The definitive remediation for CVE-2026-39377 is upgrading the nbconvert software package to version 7.17.1 or later. System administrators and developers should proactively audit their Python virtual environments, container images, and continuous integration pipelines to identify vulnerable installations. The update process utilizes standard Python package managers, executing commands such as pip install --upgrade nbconvert.
Organizations incapable of immediately deploying the patched version can implement functional configuration workarounds. The primary attack vector is neutralized by disabling the ExtractAttachmentsPreprocessor during document conversion operations. Furthermore, users should strictly ensure that the embed_images parameter remains configured to False when converting notebooks from untrusted sources.
Defense-in-depth strategies restrict the theoretical impact of successful exploitation. Administrators should configure the execution environments for file converters utilizing the principle of least privilege. Executing the conversion process within isolated container environments or highly restricted system user accounts prevents attackers from writing payloads to critical system directories.
Security monitoring systems can detect exploitation attempts by analyzing application logs and filesystem telemetry. The patched version of nbconvert generates specific warning messages stating Attachment filename contained path components when it encounters malicious attachment keys. File integrity monitoring solutions provide secondary detection capabilities by alerting administrators to unauthorized file modifications outside of designated output directories.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
nbconvert Project Jupyter | >= 6.5, < 7.17.1 | 7.17.1 |
| Attribute | Detail |
|---|---|
| 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 |
The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.