GHSA-654x-cwwv-5j9c

Suggest an improvement
Source
https://github.com/advisories/GHSA-654x-cwwv-5j9c
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-654x-cwwv-5j9c/GHSA-654x-cwwv-5j9c.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-654x-cwwv-5j9c
Aliases
Published
2026-10-23T21:53:21Z
Modified
2026-10-23T22:00:03Z
Severity
  • 6.3 (Medium) CVSS_V4 - 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 CVSS Calculator
Summary
Pillow: Arrow export leaks stale heap memory when PILLOW_ALIGNMENT > 1
Details

Summary

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.

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"
}
References

Affected packages

PyPI / pillow

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
11.2.1
Fixed
13.0.0

Affected versions

11.*
11.2.1
11.3.0
12.*
12.0.0
12.1.0
12.1.1
12.2.0
12.3.0

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-654x-cwwv-5j9c/GHSA-654x-cwwv-5j9c.json"