CVE-2026-128067: CVE-2026-128067: Out-of-Bounds Heap Read and Write in Pillow libtiff Encoder via Geometry Tag Overrides
CVE-2026-128067: Out-of-Bounds Heap Read and Write in Pillow libtiff Encoder via Geometry Tag Overrides Vulnerability ID: CVE-2026-128067 CVSS Score: 8.4 Published: 2026-11-12 CVE-2026-128067 is a memory corruption
CVE-2026-128067: Out-of-Bounds Heap Read and Write in Pillow libtiff Encoder via Geometry Tag Overrides
Vulnerability ID: CVE-2026-128067
CVSS Score: 8.4
Published: 2026-11-12
CVE-2026-128067 is a memory corruption vulnerability in Pillow (versions 2.3.0 through 12.3.0) occurring when saving compressed TIFF images via the underlying libtiff encoder. By supplying crafted image geometry tags through exif=, tiffinfo=, or a source TIFF IFD, an attacker can override the scanline dimensions configured in libtiff while Pillow allocates the internal row buffer based strictly on the physical image dimensions. This mismatch induces an out-of-bounds heap read during scanline encoding, and escalates to an out-of-bounds heap write when TIFF Predictor 2 (horizontal differencing) is enabled.
TL;DR
Pillow versions 2.3.0 through 12.3.0 allow caller-supplied TIFF tags (ImageWidth, ImageLength, SamplesPerPixel) to override libtiff encoder geometry while allocating the scanline buffer from the actual image size. This causes an out-of-bounds heap read (leaking memory into the output TIFF or crashing the process) and an out-of-bounds heap write when TIFF Predictor 2 is active. Fixed in Pillow 13.0.0.
β οΈ Exploit Status: POC
Technical Details
- Vulnerability ID: CVE-2026-128067 / GHSA-xcvg-w56q-r89m
- Weakness Class: CWE-787 (Out-of-bounds Write) / CWE-125 (Out-of-bounds Read)
- CVSS v4.0 Score: 8.4 HIGH (CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:L/VA:H/SC:N/SI:N/SA:N)
- Affected Component: Pillow TiffImagePlugin._save & ImagingLibTiffEncode (TiffDecode.c)
- Affected Versions: Pillow >= 2.3.0, <= 12.3.0
- Patched Version: Pillow 13.0.0
- Impact: Heap memory disclosure into output TIFF, process crash (DoS), and heap corruption
- Exploit Status: Proof-of-Concept Verified (Not in CISA KEV)
Affected Systems
- Pillow (Python Imaging Library fork) >= 2.3.0, <= 12.3.0
-
Pillow: >= 2.3.0, <= 12.3.0 (Fixed in:
13.0.0)
Code Analysis
Commit: ec5f1cb
Reject TIFF scanline sizes larger than the row buffer in ImagingLibTiffEncode and lock geometry tags.
diff --git a/src/libImaging/TiffDecode.c b/src/libImaging/TiffDecode.c
index daf7620a8cc..f985c604239 100644
--- a/src/libImaging/TiffDecode.c
+++ b/src/libImaging/TiffDecode.c
@@ -792,6 +792,14 @@ ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int byt
TIFF *tiff = clientstate->tiff;
if (state->state == 0) {
+ // state->buffer holds one row of the image, but TIFFWriteScanline reads
+ // a scanline of the size described by the IMAGEWIDTH, SAMPLESPERPIXEL
+ // and BITSPERSAMPLE tags, so these must not describe a larger row.
+ if (TIFFScanlineSize64(tiff) > (uint64_t)state->bytes) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
// Encoding line by line
while (state->y < state->ysize) {
state->shuffle(
Commit: 53318b5
Merge pull request #10226 remediating TIFF geometry tag override buffer overflow.
diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py
index a84b557cf09..5bd5369c27a 100644
--- a/Tests/test_file_libtiff.py
+++ b/Tests/test_file_libtiff.py
@@ -395,6 +395,24 @@ def test_non_bytes(
with pytest.raises(ValueError, match="Incorrect tag value type"):
im.save(out, tiffinfo=ifd)
+ @pytest.mark.parametrize(
+ "tiffinfo",
+ (
+ {TiffImagePlugin.IMAGEWIDTH: 1 << 27},
+ {TiffImagePlugin.SAMPLESPERPIXEL: 3},
+ ),
+ )
+ def test_geometry_tags(
+ self, tiffinfo: dict[int, int], monkeypatch: pytest.MonkeyPatch, tmp_path: Path
+ ) -> None:
+ # libtiff reads a scanline of the size described by the IMAGEWIDTH,
+ # SAMPLESPERPIXEL and BITSPERSAMPLE tags from a buffer that only holds one
+ # row of the image, so a tag describing a larger row must be rejected.
+ monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)
+
+ out = tmp_path / "temp.tif"
+ im = hopper("L")
+ with pytest.raises(OSError, match="encoder error -8"):
+ im.save(out, tiffinfo=tiffinfo)
Mitigation Strategies
- Upgrade Pillow to version 13.0.0 or later to enforce C-level scanline bounds checking in ImagingLibTiffEncode.
- Filter and strip geometry and predictor tags (256, 257, 258, 277, 284, 317) from untrusted exif, tiffinfo, and source IFD dictionaries prior to saving TIFF images.
- Disable libtiff encoding (ensure TiffImagePlugin.WRITE_LIBTIFF is False and avoid compressed TIFF formats) if compressed TIFF output is not required.
Remediation Steps:
- Identify all Python environments and container images utilizing Pillow versions >= 2.3.0 and < 13.0.0.
- Update dependency manifests (requirements.txt, pyproject.toml, Pipfile) to require pillow>=13.0.0.
- If immediate upgrade is blocked, deploy an application-level wrapper around Image.save() to remove tags 256 (ImageWidth), 257 (ImageLength), 258 (BitsPerSample), 277 (SamplesPerPixel), 284 (PlanarConfiguration), and 317 (Predictor).
- Verify the remediation using regression tests that pass oversized IMAGEWIDTH and SAMPLESPERPIXEL tags with WRITE_LIBTIFF=True and confirm OSError (encoder error -8) is raised.
References
- GitHub Security Advisory GHSA-xcvg-w56q-r89m
- Pillow Merge Commit 53318b50e8e9e85a57d033d4d879e1398d97aeb1
- Pillow Fix Commit ec5f1cbcf67275641abaad5c065ffb64a0a804a9
- Pillow 13.0.0 Release
- Pillow Pull Request #10226
- CVE.org Record for CVE-2026-128067
- NVD Entry for CVE-2026-128067
- CVE List V5 JSON Record for CVE-2026-128067
Read the full report for CVE-2026-128067 on our website for more details including interactive diagrams and full exploit analysis.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.