{"id":"GHSA-654x-cwwv-5j9c","aliases":["CVE-2026-114501","PYSEC-2026-4336"],"title":"Pillow: Arrow export leaks stale heap memory when PILLOW_ALIGNMENT > 1","titleSource":"OSV","descriptionSource":"OSV","declaredSeverity":"MODERATE","description":"### Summary\n\nWhen [`PILLOW_ALIGNMENT`](https://pillow.readthedocs.io/en/stable/reference/block_allocator.html#memory-pools) is set above 1, exporting an image to Arrow returns uninitialized heap memory mixed in with the pixel data. That memory can include pixels from images the process freed earlier. \n\n### Details\n\nWith an alignment above 1, the default allocator pads each row up to `aligned_linesize` and starts the first row at an aligned offset into the block. It then exports `im->blocks[0].ptr` as `xsize * ysize` tightly packed pixels, so exported data includes the padding bytes, and can include a few bytes from before the first row.\n\nTested vulnerable on 11.2.1, 12.3.0, 4c1ed27a5.\n\n### PoC\n\nWhether things leak may depend on allocator configuration. This does show a leak on my Mac.\n\n```python\nimport os\n\nos.environ[\"PILLOW_ALIGNMENT\"] = \"64\"\n\nfrom PIL import Image\n\n# Image A: 64 px wide, so its rows fill the whole aligned stride\na = Image.new(\"L\", (64, 40), 0x41).transpose(Image.Transpose.FLIP_LEFT_RIGHT)\ndel a\n\n# Image B: 61 px wide, so each row has 3 bytes of padding; its pixels are all 0\nb = Image.new(\"L\", (61, 40), 0).transpose(Image.Transpose.FLIP_LEFT_RIGHT)\n\ntry:\n    exported = Image.fromarrow(b, b.mode, b.size).tobytes()\nexcept ValueError as e:\n    print(\"Not vulnerable:\", e)\nelse:\n    if leaked := len(exported) - exported.count(0):\n        raise RuntimeError(f\"{leaked} of {len(exported)} exported bytes are not B's pixels\")\n```\n\n### Impact\n\nInformation disclosure for applications that set `PILLOW_ALIGNMENT` and export images to Arrow. Likely any image whose row length isn't a multiple of the alignment will do. In a service handling several users' images, one user's exported data can contain pixels from another user's image, or other stale heap contents.","severity":"medium","score":6.3,"published":"2026-10-21T22:16:49.410Z","modified":"2026-10-28T11:10:57.789Z","withdrawn":false,"knownExploited":false,"affected":[{"ecosystem":"PyPI","name":"pillow","sources":[{"name":"OSV · GHSA-654x-cwwv-5j9c","url":"https://osv.dev/vulnerability/GHSA-654x-cwwv-5j9c"}],"ranges":[{"events":[{"introduced":"11.2.1"},{"fixed":"13.0.0"}],"type":"ECOSYSTEM"}],"versions":["11.2.1","11.3.0","12.0.0","12.1.0","12.1.1","12.2.0","12.3.0"],"fixed":["13.0.0"]},{"ecosystem":"PyPI","name":"pillow","sources":[{"name":"OSV · PYSEC-2026-4336","url":"https://osv.dev/vulnerability/PYSEC-2026-4336"}],"ranges":[{"events":[{"introduced":"11.2.1"},{"fixed":"13.0.0"}],"type":"ECOSYSTEM"}],"versions":["11.2.1","11.3.0","12.0.0","12.1.0","12.1.1","12.2.0","12.3.0"],"fixed":["13.0.0"]}],"sourceAffected":[],"references":["https://github.com/python-pillow/Pillow/security/advisories/GHSA-654x-cwwv-5j9c","https://nvd.nist.gov/vuln/detail/CVE-2026-114501","https://github.com/python-pillow/Pillow/pull/10172","https://github.com/python-pillow/Pillow/commit/19f64946eb247b973dd4560be7dea3bf979d2e6a","https://github.com/python-pillow/Pillow","https://github.com/python-pillow/Pillow/releases/tag/13.0.0"],"sources":[{"name":"OSV","id":"GHSA-654x-cwwv-5j9c","modified":"2026-10-28T11:10:57.789019651Z","url":"https://osv.dev/vulnerability/GHSA-654x-cwwv-5j9c"},{"name":"OSV","id":"PYSEC-2026-4336","modified":"2026-10-28T11:00:02.234829126Z","url":"https://osv.dev/vulnerability/PYSEC-2026-4336"}],"assessments":[{"source":"OSV","vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N","score":6.3},{"source":"OSV","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","score":5.3}],"products":[],"remediation":[],"kev":{"status":"not-listed","checkedAt":"2026-10-28T22:15:33.378Z"},"coverage":[{"source":"NVD","status":"available","checkedAt":"2026-10-28T11:35:34.964Z","attemptedAt":"2026-10-28T11:35:34.964Z"},{"source":"GHSA","status":"available","checkedAt":"2026-10-28T11:35:34.972Z","attemptedAt":"2026-10-28T11:35:34.972Z"},{"source":"EUVD","status":"available","checkedAt":"2026-10-28T11:35:37.216Z","attemptedAt":"2026-10-28T11:35:37.216Z"},{"source":"EPSS","status":"available","checkedAt":"2026-10-28T11:35:34.969Z","attemptedAt":"2026-10-28T11:35:34.969Z"}],"evidence":[{"source":"NVD","id":"CVE-2026-114501","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-114501","modified":"2026-10-27T14:29:01.280","score":6.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","checkedAt":"2026-10-28T11:35:34.964Z"},{"source":"NVD","id":"CVE-2026-114501","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-114501","modified":"2026-10-27T14:29:01.280","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","checkedAt":"2026-10-28T11:35:34.964Z"},{"source":"GitHub Advisory Database","id":"GHSA-654x-cwwv-5j9c","url":"https://github.com/advisories/GHSA-654x-cwwv-5j9c","modified":"2026-10-23T21:53:25Z","checkedAt":"2026-10-28T11:35:34.972Z"},{"source":"FIRST EPSS","id":"CVE-2026-114501","url":"https://www.first.org/epss/","probability":0.00469,"percentile":0.40405,"date":"2026-10-27","checkedAt":"2026-10-28T11:35:34.969Z"},{"source":"ENISA EUVD","id":"EUVD-2026-107575","url":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-107575","modified":"Oct 21, 2026, 9:17:09 PM","score":6.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N","checkedAt":"2026-10-28T11:35:37.216Z"}]}