Jul 21, 2026·6 min read·28 visits
A signed integer overflow in Pillow before 12.3.0 allows unauthenticated remote attackers to bypass memory safety checks and perform a native heap out-of-bounds write via crafted coordinates, leading to a denial of service.
A critical signed 32-bit integer overflow vulnerability was identified in Pillow (Python Imaging Library) versions prior to 12.3.0. The vulnerability resides within the native C extension library (libImaging) during coordinate and bounding box calculations in functions like ImagingPaste and ImagingFill2. Exploitation can bypass bounds and clipping safety checks, leading to a controlled heap backward underwrite and application crash.
Pillow, the standard Python Imaging Library fork, processes digital images using a high-performance native C extension layer named libImaging. This layer is responsible for intensive pixel manipulations, layout calculations, and coordinate transformation mapping. Because these operations are executed in native C, any parsing or calculation of dimensions must be strictly validated before memory is allocated or accessed.
The vulnerability is classified as a signed 32-bit integer overflow (CWE-190) that cascades into an out-of-bounds write (CWE-787). It affects multiple high-level, coordinate-based APIs, including Image.paste, Image.crop, and Image.alpha_composite. When an application accepts untrusted coordinates from external inputs, it exposes this internal native layer to arbitrary input manipulation.
By supplying coordinates close to the bounds of a signed 32-bit integer, an attacker can manipulate the internal dimension calculations. This manipulation bypasses safety boundaries and allows write access outside the allocated target row buffers. The consequence is native heap memory corruption, typically leading to immediate program termination.
The root cause of this vulnerability lies in the mathematical subtraction used to calculate the height and width of image bounding boxes within Pasteurization and Filling utilities. Specifically, the functions ImagingPaste and ImagingFill2 in src/libImaging/Paste.c calculate the xsize and ysize of the destination region using the equations: xsize = dx1 - dx0 and ysize = dy1 - dy0. Because dx0, dy0, dx1, and dy1 are standard signed 32-bit integers, their values can range from -2147483648 to 2147483647.
When dx0 is set to a large positive value such as 2147483646 and dx1 is set to a large negative value such as -2147483648, the subtraction results in -4294967294. In signed 32-bit two's complement representation, this mathematical value wraps around and is interpreted as positive 2. This wrapped value matches the positive width of the incoming source image, successfully bypassing the inequality mismatch safety checks.
Furthermore, the subsequent boundary check compares dx0 + xsize against the target output image width. Since dx0 is 2147483646 and xsize is evaluated as 2, their sum is 2147483648, which wraps around to -2147483648. Because this negative value is mathematically smaller than the target output image width, the boundary check fails to identify an out-of-bounds condition and permits the execution flow to continue unchecked.
To understand the exact flaw and its resolution, we must analyze the code structure before and after the security patch. In the vulnerable version of src/libImaging/Paste.c, variables storing sizes are declared as standard 32-bit signed integers, which are susceptible to overflow.
// VULNERABLE CODE PATH (Paste.c)
int xsize, ysize;
// Subtraction performed in 32-bit signed arithmetic
xsize = dx1 - dx0;
ysize = dy1 - dy0;The corresponding fix, introduced in commit ceefc348eb3c3844c7f9796ef2cc3a7dd5fbba7b, promotes the size tracking variables to 64-bit integers and introduces explicit casting. This prevents the wraparound behavior during subtraction.
// PATCHED CODE PATH (Paste.c)
int64_t xsize, ysize;
// Subtraction promoted to 64-bit space to prevent overflow
xsize = (int64_t)dx1 - dx0;
ysize = (int64_t)dy1 - dy0;By casting dx1 to a 64-bit signed integer before subtraction, the compiler executes the operation in 64-bit space. The intermediate value of -4294967294 is preserved accurately as a negative 64-bit integer, which fails the mismatch comparison against the positive 32-bit source image size and triggers an early error exit.
Exploitation of this vulnerability requires the ability to supply coordinate parameters to Pillow APIs. When the coordinates bypass the boundary checks, the application proceeds to the pixel copying stage, calculating a target memory address via pointer arithmetic: Row Destination + (dx0 * pixelsize).
If the color mode is RGBA, the pixelsize is 4 bytes. For a dx0 value of 2147483646, the multiplication is computed as 2147483646 * 4, which equals 8589934584. In 32-bit signed math, this calculation wraps around to -8, which is then sign-extended on 64-bit systems to a large negative offset. Consequently, the destination pointer is adjusted backward by 8 bytes.
When memcpy is invoked to copy the row data, the write operation begins exactly 8 bytes before the beginning of the allocated heap row buffer, corrupting metadata or adjacent heap chunks. The overall process and physical memory layout can be visualized in the diagram below:
The security consequences of a native heap backward underwrite are severe. Memory corruptions occurring in heap chunk headers can compromise the integrity of the dynamic memory allocator. This corruption typically triggers immediate application termination or a segmentation fault when the affected or adjacent heap blocks are later freed by the system.
An attacker can utilize this vulnerability to perform targeted denial of service attacks against services processing user-supplied images or bounding boxes. If the environment operates in a multi-threaded process or within a persistent worker architecture, a single exploit payload can terminate the processing daemon and disrupt service availability.
While remote code execution is theoretically possible by overwriting adjacent function pointers or critical class metadata, the level of precision required depends heavily on the specific allocator behavior and surrounding heap layout. No weaponized exploits for remote code execution have been publicly observed in active campaigns, classifying the threat maturity primarily as a denial of service vector.
The primary remediation for this vulnerability is upgrading the Pillow dependency to version 12.3.0 or higher. This release integrates the 64-bit integer calculation patch, which completely mitigates the integer overflow condition.
If upgrading immediately is not feasible, application-layer coordinate validation must be enforced. Any coordinate inputs passed to Image.paste, Image.crop, or Image.alpha_composite must be restricted to safe, realistic limits corresponding to the physical boundaries of the canvas. The following validation check illustrates how to intercept unsafe inputs:
def validate_coordinates(box, max_width, max_height):
if box:
for coord in box:
if not (-65536 <= coord <= 65536):
raise ValueError("Coordinate exceeds safe limit")Additionally, high-risk image parsing workflows should run within isolated, sandboxed environments with low privileges. Restricting container memory space and applying seccomp profiles can limit the potential blast radius of native heap memory corruption exploits.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Pillow Python Pillow | < 12.3.0 | 12.3.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-190, CWE-787 |
| Attack Vector | Network (Remote) |
| CVSS Score | 7.5 (High) |
| EPSS Score | 0.0039 (Percentile: 31.40%) |
| Impact | Denial of Service, Native Heap Corruption |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
The software performs an calculation that can produce an integer overflow or wraparound, which can lead to unexpected behavior or security issues.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.