Pillow is the friendly fork of the Python Imaging Library (PIL), used by thousands of developers to process images. But in late 2021, researchers found a nasty bug: CVE-2022-22816, a buffer over-read in path_getbbox within path.c. Before version 9.., you could trigger this issue during ImagePath.Path initialization, potentially leaking memory contents or crashing your program.
Let’s break down what this vulnerability is, how it happens, what an exploit looks like, and how you can stay safe.
What Is CVE-2022-22816?
CVE-2022-22816 is a vulnerability in Pillow versions before 9... It lives in the function path_getbbox in path.c. Here’s what the official CVE says:
> path_getbbox in path.c in Pillow before 9.. has a buffer over-read during initialization of ImagePath.Path.
> — NVD
What’s a Buffer Over-Read?
A buffer over-read happens when a program tries to read more bytes from a buffer (block of memory) than the buffer actually holds. This can cause the program to crash (denial of service) or, worse, leak memory to attackers.
How Does the Vulnerability Work?
The bug is in C code under the hood of Pillow’s ImagePath.Path. When you initialize a Path object with crafted data, the path_getbbox function could try to read past the allocated memory.
Here’s a simplified C-like idea of what could go wrong
void path_getbbox(PathObject *self, ...) {
double x, y;
// ...
for (i = ; i < self->count; i += 2) {
x = self->xy[i];
y = self->xy[i+1]; // uh-oh! What if count is odd? Reads past buffer.
// do stuff
}
}
If self->xy is an odd-length array, y = self->xy[i+1] loads invalid memory. In Python, you might trigger this like:
from PIL import ImagePath
coords = [1, 2, 3] # Odd length!
path = ImagePath.Path(coords)
bbox = path.getbbox() # Crashes, reads out of bounds
Older Pillow versions don’t check if the coordinate list is even-length. If you input an array like [1, 2, 3], it will read memory after the last valid coordinate.
Proof-of-Concept Exploit
Below is a PoC that demonstrates the bug. If you're running Pillow <9.., expect possible crashes or strange output:
from PIL import ImagePath
# This should be [x, y, x1, y1, ...], always even-length.
malicious_coords = [100, 200, 300] # Odd number of items!
try:
path = ImagePath.Path(malicious_coords)
bbox = path.getbbox()
print("BBox:", bbox)
except Exception as e:
print("Crashed:", e)
Real-World Impact
For most apps, this is a Denial of Service bug: someone submits a weird path, your app crashes. For hosted Python services, especially where users can upload or process images via Pillow, there's a risk of exploiting this to disrupt your service or leak information.
How Was It Fixed?
Pillow patched this issue in version 9.. (Nov 2021) by validating input lengths before processing them in C code:
- Now, if the coordinates list length isn’t a multiple of two, ImagePath.Path will raise an exception right away, before calling into vulnerable C code.
Relevant code from the patch
# In Python layer
if len(coords) % 2 != :
raise ValueError("Coordinate list length must be even")
References
- NVD entry for CVE-2022-22816
- Pillow Security Release Notes
- GitHub Patch
- Pillow Issue #5827
2. Validate input.
If you’re dealing with user-supplied image data or coordinate lists, make sure they’re sanitized in your own code.
3. Monitor for security news.
Subscribe to Pillow security advisories.
Patch and stay safe!
Don't let a simple image processing bug bring down your app. Always keep your dependencies up-to-date, and stay alert for new CVEs!
Timeline
Published on: 01/10/2022 14:12:00 UTC
Last modified on: 02/16/2022 18:49:00 UTC