Mar 20, 2026·6 min read·3 visits
A path traversal vulnerability (CWE-22) in pydicom's FileSet parsing allows local arbitrary file operations via maliciously crafted DICOMDIR files. Update to version 3.0.2 or 2.4.5 to mitigate.
CVE-2026-32711 is a high-severity path traversal vulnerability in the pydicom Python library, affecting versions 2.0.0-rc.1 through 3.0.1. The flaw resides in the FileSet implementation, where insufficient validation of the ReferencedFileID attribute allows malicious DICOMDIR files to perform out-of-bounds file reads, copies, or deletions.
The pydicom Python library provides parsing and manipulation capabilities for DICOM files, a standard format in medical imaging. A core component of this standard is the DICOMDIR file, which acts as an index for a set of related DICOM files known as a File-set. The pydicom.fileset.FileSet class implements the logic for loading, modifying, and exporting these collections.
CVE-2026-32711 identifies a CWE-22 Path Traversal vulnerability within the FileSet parsing logic. The vulnerability specifically affects the handling of the ReferencedFileID attribute found in directory records. Insufficient sanitization of this attribute allows a malicious DICOMDIR file to reference arbitrary files outside the intended File-set root directory.
Exploitation requires a victim to process a weaponized DICOMDIR file using a vulnerable version of pydicom. Depending on the subsequent operations performed on the FileSet object, an attacker can achieve arbitrary file read, copy, or deletion on the victim's host filesystem. The impact is highly dependent on the privileges of the executing Python process.
The vulnerability originates from an unsafe interaction between user-supplied paths and Python's pathlib.Path module. When joining paths using the / operator, pathlib completely discards the left-hand operand if the right-hand operand evaluates to an absolute path. This behavior allows an attacker to bypass intended directory restrictions simply by supplying a path beginning with a root descriptor, such as / on Linux or C:\ on Windows.
In vulnerable versions of pydicom, the FileSet.load() method processes the ReferencedFileID to locate referenced files. The library invokes .resolve(strict=True) on the constructed path to verify that the target file exists on the filesystem. However, it fails to implement a containment check to verify that the resolved, absolute path remains a child of the designated File-set root directory.
Once the unvalidated path is loaded into the FileSet object, it becomes subject to standard operations. Methods such as FileSet.copy(), FileSet.write(), and FileSet.remove() utilize the stored path without further validation. If a victim script invokes FileSet.copy(), the library will read the file from the attacker-controlled absolute path and write it to the specified output destination, completing the data exfiltration chain.
The remediation for CVE-2026-32711 introduces explicit path validation to enforce directory containment. The patch, implemented in commit 6414f01a053dff925578799f5a7208d2ae585e82, deprecates the vulnerable _file_id property. It replaces it with a dedicated file_id_path method that requires the root path as an argument for contextual validation.
def file_id_path(self, root_path: Path) -> Path | None:
# Attribute extraction logic omitted for brevity
path = Path(...)
if path is not None:
if path.anchor or not (
(root_path / path).resolve().is_relative_to(root_path)
):
raise PermissionError(
f"ReferencedFileID ('{path}') must be inside the DICOMDIR root path"
)
return pathThe patched logic implements two critical security checks. First, it evaluates path.anchor to explicitly reject any absolute paths, directly mitigating the pathlib joining behavior. Second, it resolves the combined path and uses is_relative_to(root_path) to ensure that relative traversals utilizing ../ sequences cannot escape the designated root directory. This comprehensive approach effectively eliminates the path traversal vector.
Exploiting CVE-2026-32711 requires the construction of a malicious DICOMDIR file. An attacker modifies a valid directory record, altering the ReferencedFileID attribute to point to a target file on the victim's system. The payload can be an absolute path, such as /etc/passwd, or a relative traversal path depending on the attacker's knowledge of the execution environment.
The attacker must then deliver the modified DICOMDIR file to the victim, typically bundled within a larger medical imaging dataset. The attack relies on social engineering or standard data ingestion workflows to prompt the victim to process the dataset. No specialized network access or authentication is required by the attacker, as the execution occurs entirely locally on the victim's machine.
from pydicom.fileset import FileSet
# Victim loads the malicious DICOMDIR
fs = FileSet("malicious_dicom_dir/DICOMDIR")
# The library reads from the traversal path and writes to the output
fs.copy("output_folder/")> [!NOTE]
> The specific operation invoked by the victim dictates the final impact. While copy() results in arbitrary file read, a combination of remove() and write(use_existing=True) can lead to arbitrary file deletion or modification outside the intended directory structure.
The NVD assigned a CVSS v3.1 base score of 7.8 to CVE-2026-32711, represented by the vector CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. The Attack Vector is classified as Local because the exploit is delivered via a file rather than an active network connection. User Interaction is required, as the victim must actively invoke the pydicom parsing logic on the malicious file.
The impact metrics for Confidentiality, Integrity, and Availability are all rated High. An attacker can achieve complete compromise of files accessible to the Python process. Reading sensitive configuration files degrades confidentiality, while overwriting or deleting critical system files impacts integrity and availability.
The Exploit Prediction Scoring System (EPSS) assigns a probability score of 0.00016, placing the vulnerability in the 3.29th percentile. This low score indicates a minimal historical likelihood of exploitation in the wild for this specific class of vulnerability in a specialized Python library. The vulnerability is not currently listed in the CISA Known Exploited Vulnerabilities (KEV) catalog.
The maintainers of pydicom addressed the vulnerability in two separate release branches. Users operating on the modern 3.x branch must upgrade to version 3.0.2 to receive the security patch. For environments constrained to the 2.x branch, the fix was backported and released in version 2.4.5.
Organizations utilizing pydicom to process untrusted or externally sourced DICOM datasets should apply the updates immediately. In scenarios where immediate patching is prohibited by change management policies, defensive operations must be implemented. Processing untrusted datasets within tightly restricted sandbox environments or unprivileged containers reduces the impact of a successful path traversal.
System administrators should enforce the principle of least privilege on processes invoking pydicom. Ensuring the Python execution environment only possesses read and write access to dedicated processing directories prevents the traversal from reaching sensitive operating system files. Regular auditing of dependencies via software composition analysis tools will identify vulnerable instances of the library across the infrastructure.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
pydicom pydicom | >= 2.0.0-rc.1, <= 3.0.1 | 3.0.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Local |
| CVSS Score | 7.8 |
| EPSS Score | 0.00016 |
| Impact | High (Confidentiality, Integrity, Availability) |
| Exploit Status | Proof of Concept |
| CISA KEV | False |
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')