GHSA-654X-CWWV-5J9C
Vulnerability from github – Published: 2026-10-23 21:53 – Updated: 2026-10-23 21:53Summary
When PILLOW_ALIGNMENT 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.
Details
With 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.
Tested vulnerable on 11.2.1, 12.3.0, 4c1ed27a5.
PoC
Whether things leak may depend on allocator configuration. This does show a leak on my Mac.
import os
os.environ["PILLOW_ALIGNMENT"] = "64"
from PIL import Image
# Image A: 64 px wide, so its rows fill the whole aligned stride
a = Image.new("L", (64, 40), 0x41).transpose(Image.Transpose.FLIP_LEFT_RIGHT)
del a
# Image B: 61 px wide, so each row has 3 bytes of padding; its pixels are all 0
b = Image.new("L", (61, 40), 0).transpose(Image.Transpose.FLIP_LEFT_RIGHT)
try:
exported = Image.fromarrow(b, b.mode, b.size).tobytes()
except ValueError as e:
print("Not vulnerable:", e)
else:
if leaked := len(exported) - exported.count(0):
raise RuntimeError(f"{leaked} of {len(exported)} exported bytes are not B's pixels")
Impact
Information 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.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "Pillow"
},
"ranges": [
{
"events": [
{
"introduced": "11.2.1"
},
{
"fixed": "13.0.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-114501"
],
"database_specific": {
"cwe_ids": [
"CWE-226",
"CWE-908"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-23T21:53:21Z",
"nvd_published_at": "2026-10-21T22:16:49Z",
"severity": "MODERATE"
},
"details": "### 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-\u003eblocks[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\u0027s 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\u0027t a multiple of the alignment will do. In a service handling several users\u0027 images, one user\u0027s exported data can contain pixels from another user\u0027s image, or other stale heap contents.",
"id": "GHSA-654x-cwwv-5j9c",
"modified": "2026-10-23T21:53:21Z",
"published": "2026-10-23T21:53:21Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/python-pillow/Pillow/security/advisories/GHSA-654x-cwwv-5j9c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-114501"
},
{
"type": "WEB",
"url": "https://github.com/python-pillow/Pillow/pull/10172"
},
{
"type": "WEB",
"url": "https://github.com/python-pillow/Pillow/commit/19f64946eb247b973dd4560be7dea3bf979d2e6a"
},
{
"type": "PACKAGE",
"url": "https://github.com/python-pillow/Pillow"
},
{
"type": "WEB",
"url": "https://github.com/python-pillow/Pillow/releases/tag/13.0.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "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",
"type": "CVSS_V4"
}
],
"summary": "Pillow: Arrow export leaks stale heap memory when PILLOW_ALIGNMENT \u003e 1"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.