Safeguard
Security Guides

Pillow (PIL) Security Guide (2026)

Pillow is the default image library for Python — and because it parses untrusted image bytes and once shipped an eval-based ImageMath, it has a long, real CVE history spanning arbitrary code execution and native buffer overflows.

Priya Mehta
Security Researcher
6 min read

Pillow is the de facto image-processing library for Python, the actively maintained fork of the original PIL. If a Python application opens, resizes, converts, or thumbnails an image, it is almost certainly using Pillow — directly, or transitively through web frameworks, document pipelines, machine-learning preprocessing, and avatar-upload handlers. On PyPI it sees enormous download volume. That ubiquity is exactly what makes it security-relevant: Pillow's core job is to parse attacker-controlled bytes in dozens of image formats, many implemented in C, and for years it also shipped an ImageMath module that evaluated expressions with Python's eval. The result is one of the richest CVE histories of any Python package, and unlike some libraries, most of these are not disputed — they are genuine code-execution and memory-safety bugs.

The notable historical CVEs

Pillow's advisories cluster in two places: unsafe expression evaluation in ImageMath, and memory bugs in the native format decoders. These are all real, published advisories:

  • CVE-2022-22817PIL.ImageMath.eval allowed evaluation of arbitrary expressions, so an expression such as one calling exec could run arbitrary code. Pillow 9.0.0 restricted the top-level builtins available to ImageMath.eval, and 9.0.1 closed the remaining gap where builtins were still reachable through lambda expressions.
  • CVE-2023-50447 — a different PIL.ImageMath.eval code-execution path, this time via the environment argument: an attacker who controls the keys passed in the environment could execute arbitrary code. It affects Pillow through 10.1.0 and is fixed in 10.2.0, which rejects keys matching builtins or containing double underscores.
  • CVE-2024-28219 — a buffer overflow in _imagingcms.c, where two strcpy calls could copy more data than a fixed-length buffer held. Fixed in 10.3.0 by switching to bounded strncpy.

Pillow's earlier history is dense with format-decoder denial-of-service and out-of-bounds issues as well — for example the cluster of 2021 advisories affecting the BLP, ICNS, ICO, PSD, FLI, and EPS decoders (CVE-2021-27921 through CVE-2021-28678) — which is why staying on a current release, rather than tracking individual CVEs, is the durable strategy.

Common misuse and risks

  • Calling ImageMath.eval on untrusted expressions or environments. This is the sharpest edge. Both CVE-2022-22817 and CVE-2023-50447 turn ImageMath.eval into arbitrary code execution when an attacker influences the expression or the environment keys. Treat any ImageMath.eval fed by external input as a live remote-code-execution risk.
  • Opening attacker-supplied images without limits. Pillow decodes many formats in C. A crafted file can trigger a decoder bug or exhaust memory, so an unbounded upload handler that calls Image.open on anything is exposed to the decoder CVEs.
  • Decompression bombs. A small file can declare enormous dimensions and expand to gigabytes in memory. Pillow has a MAX_IMAGE_PIXELS guard, but code that raises or disables it reopens the risk.
  • Running an old, pinned Pillow. Because Pillow is often transitive, a stale version can persist behind a framework long after the fixes landed.

How to use Pillow safely

Set the version floor: run a current Pillow release (the 11.x line in 2026) and never operate below 10.3.0, which fixes the _imagingcms buffer overflow and sits above both ImageMath.eval fixes. Anything older leaves at least one code-execution or memory-safety path open.

Then treat image handling as untrusted-input processing:

  • Do not pass untrusted data into ImageMath.eval. If you do not need it, do not import it. If you must evaluate image math, build the expression yourself from a fixed template and never let a caller supply the expression string or environment keys.
  • Keep the pixel-count guard on. Leave Image.MAX_IMAGE_PIXELS at its default and let Pillow raise on suspiciously large images rather than disabling the check.
  • Bound uploads. Enforce maximum file size and dimensions before decoding, and reject formats you do not actually support instead of accepting everything Image.open can parse.
  • Sandbox heavy decoding. For high-risk intake, decode in an isolated worker process with restricted memory, filesystem, and network access so a decoder bug cannot pivot.
  • Pin and monitor. Lock Pillow and watch for new decoder advisories, which arrive regularly.

How to monitor Pillow with SCA and reachability

Pillow shows up across web, document, and ML dependency trees, so a version-only scanner will flag it broadly. What decides urgency is whether you are on a patched release and whether your code actually reaches a dangerous path — an ImageMath.eval call on external input, or a decoder handling untrusted uploads.

Safeguard's software composition analysis resolves your full Python dependency graph, including the transitive Pillow you did not choose directly, and adds call-path reachability so an ImageMath.eval advisory your code can actually trigger is separated from a decoder CVE for a format you never open. Autonomous auto-fix opens a tested pull request that bumps Pillow to a safe release, and Griffin AI explains the exposure in plain terms so triage is fast. Developers run the same checks locally and in CI with the Safeguard CLI, and teams weighing coverage against cost can review the pricing.

Bring continuous, prioritized dependency analysis to your image-handling services — get started free or read the documentation.

Frequently Asked Questions

Which Pillow version is safe in 2026?

Run a current release on the 11.x line, and never operate below 10.3.0. That release fixes the _imagingcms buffer overflow (CVE-2024-28219) and sits above both ImageMath.eval code-execution fixes — CVE-2022-22817 (addressed across 9.0.0 and 9.0.1) and CVE-2023-50447 (fixed in 10.2.0). Staying current also picks up the steady stream of decoder hardening.

Is ImageMath.eval safe to use?

Only with fully trusted inputs. Two separate CVEs made ImageMath.eval a route to arbitrary code execution — one via the expression, one via the environment keys. On a current version the known bypasses are closed, but the durable posture is to never let external input reach the expression or environment, and to avoid importing ImageMath at all if you do not need it.

Can opening an image file be dangerous?

Yes. Pillow decodes many formats in C, and crafted files have triggered denial-of-service and memory bugs across decoders. Bound upload size and dimensions, keep the MAX_IMAGE_PIXELS guard enabled to catch decompression bombs, and decode untrusted images in a sandboxed worker when the intake is high-risk.

How do I know if a Pillow CVE actually affects my app?

Use reachability-aware SCA. It traces whether your code reaches the vulnerable behavior — an ImageMath.eval call on external input, or a specific decoder for a format you accept — so you can prioritize the genuinely exploitable findings over CVEs in code paths you never run.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.