Pillow, the widely used fork of the Python Imaging Library (PIL), shipped a fix in early 2021 for CVE-2020-35655, a denial-of-service vulnerability triggered by a crafted image file. The flaw allowed a small, attacker-supplied image to force Pillow's decoder to allocate a disproportionately large amount of memory during processing — a classic "decompression bomb" pattern. Any service that accepts user-uploaded images and hands them to Pillow for thumbnailing, resizing, format conversion, or metadata extraction was potentially exposed to resource-exhaustion attacks: a single malicious file, often just a few kilobytes on disk, could balloon in memory and consume CPU and RAM to the point of degrading or crashing the process that handled it.
Decompression bombs are an old and well-understood class of bug in image and archive libraries: the on-disk representation is compact, but the format's structure lets a small number of bytes describe an enormous decoded payload. Pillow actually ships built-in protections against this exact scenario — the Image.MAX_IMAGE_PIXELS threshold and the accompanying DecompressionBombWarning/DecompressionBombError — which exist specifically to stop absurdly large pixel counts from being decoded. CVE-2020-35655 mattered because a code path in one of Pillow's format decoders did not respect those guardrails consistently, letting a crafted file slip past the size sanity checks Pillow otherwise relies on and drive excessive memory allocation before the library's own safety net could intervene.
Affected versions and components
- Affected software: Pillow (the maintained PIL fork), the de facto standard imaging library for Python.
- Affected versions: All Pillow releases prior to 8.1.0.
- Fixed version: Pillow 8.1.0, which bundled fixes for a cluster of image-parsing vulnerabilities disclosed around the same time (Pillow's changelog for that release lists several CVEs addressed together, spanning multiple format decoders).
- Vulnerability class: Uncontrolled resource consumption / allocation-of-resources-without-limits (CWE-770 / CWE-400), commonly described as a "decompression bomb."
- Attack surface: Any application, service, or pipeline that uses Pillow to open, decode, transform, or otherwise process image files from an untrusted source — image upload endpoints, avatar/thumbnail generators, document/PDF-to-image converters, ML preprocessing pipelines, CI image-linting steps, and so on.
Because Pillow is a transitive dependency of an enormous number of Python packages (web frameworks' image-handling extensions, data science and ML toolchains, document generators, CMS platforms), the practical blast radius of this CVE was not limited to code that imports Pillow directly — it extended to every project that pulled in a vulnerable version through a dependency chain, often without the maintainers realizing Pillow was even in the tree.
CVSS, EPSS, and KEV context
CVE-2020-35655 is scored by NVD as a medium-severity, availability-only issue: the vulnerability does not allow an attacker to read or modify data, escalate privileges, or execute code — its entire impact is denial of service through memory/CPU exhaustion. That impact profile (confidentiality: none, integrity: none, availability: high) is consistent with the broader family of Pillow image-decoder CVEs from this disclosure round.
The vulnerability is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, and public EPSS scoring for this CVE has stayed low, reflecting the absence of evidence of widespread or automated exploitation in the wild. That doesn't mean it's safe to ignore: a low EPSS score reflects observed exploitation activity, not exploitability. Triggering the bug requires nothing more than getting a target application to decode a crafted file — a trivial bar for any service that accepts image uploads — which is exactly the kind of low-effort, high-availability-impact bug that gets rediscovered and weaponized opportunistically long after initial disclosure, especially against services that never patched.
Timeline
- Pre-disclosure: The issue was identified as part of a broader security review of Pillow's format decoders, alongside several related out-of-bounds-read and buffer-overflow findings affecting other image formats.
- Coordinated fix: The Pillow maintainers addressed CVE-2020-35655 together with the other findings from that review in a single hardening release.
- Fix released: Pillow 8.1.0, published in January 2021, closed the vulnerability by adding proper bounds/allocation checks to the affected decode path.
- Public disclosure: The CVE record and associated advisory were published shortly after the fixed release became available, following standard coordinated-disclosure practice for open-source library vulnerabilities.
- Post-disclosure: As with most image-library DoS bugs, no mass-exploitation campaign was publicly attributed to this specific CVE, but it remains a recurring finding in dependency and container scans years later because so many projects pin old Pillow versions.
Remediation steps
- Upgrade Pillow to 8.1.0 or later. This is the definitive fix. In practice, teams should target the latest maintained Pillow release rather than the minimum patched version, since Pillow has shipped numerous additional security fixes since 8.1.0.
- Audit transitive dependencies, not just direct ones. Pillow is frequently pulled in indirectly (via web frameworks, PDF tools, ML libraries, or CMS plugins). Run a full dependency tree resolution to confirm no vulnerable copy of Pillow is present anywhere in the graph, including in lockfiles, vendored code, or container base images.
- Enforce and tune Pillow's own decompression-bomb protections. Keep
Image.MAX_IMAGE_PIXELSat a sane, explicit value for your application rather than disabling it, and treatDecompressionBombErroras an expected, handled exception rather than an unexpected crash. - Apply resource limits at the process/container level. Independent of library-level fixes, run image-processing workers with memory ceilings, CPU quotas, and timeouts (cgroups, ulimits, container resource limits) so that any single decode operation — known vulnerability or not — cannot take down the whole host or service.
- Validate untrusted input before decoding. Check declared file size, dimensions, and format headers against reasonable application-specific limits before invoking a full decode, and process user-supplied images in isolated, sandboxed workers rather than in the main application process.
- Re-scan after patching. Confirm the fix in your build artifacts and running containers, not just your source manifests — stale base images and cached layers are a common way "already patched" dependencies keep shipping vulnerable versions.
How Safeguard Helps
CVE-2020-35655 is a textbook example of why supply chain visibility has to extend past a project's direct requirements.txt or package.json. Pillow rides into codebases as a transitive dependency of dozens of common libraries, which means teams can carry a vulnerable version for years without a single line of their own code ever importing it. Safeguard is built to close exactly that visibility gap.
- Full dependency graph analysis: Safeguard's software composition analysis resolves complete dependency trees — direct and transitive — so a vulnerable Pillow version pulled in through an unrelated package is surfaced, not missed.
- Continuous SBOM monitoring: Safeguard maintains a living software bill of materials for every scanned repository and container image, automatically flagging affected components the moment a CVE like this one is published or re-associated with new versions.
- Risk-based prioritization: Rather than treating every CVE as equally urgent, Safeguard combines severity data, exploit-maturity signals like EPSS, and KEV status to help teams focus remediation effort on the vulnerabilities most likely to matter — while still tracking lower-urgency, availability-impact issues like this one so they don't quietly age into production.
- CI/CD and registry gating: Policies can block builds or image pushes that introduce known-vulnerable Pillow versions (or any other flagged dependency), stopping the issue at the pull request or pipeline stage instead of catching it in production.
- Drift and re-introduction detection: Safeguard continuously re-scans running images and deployed artifacts, catching cases where a "fixed" dependency creeps back in through a stale base image, a reverted lockfile, or a new microservice built from an old template.
For a vulnerability class like decompression bombs — cheap to trigger, easy to overlook, and prone to lingering in dependency trees long after a fix ships — that combination of full-graph visibility, continuous monitoring, and enforceable policy is what turns "we should probably check if we're affected" into an automatic, verifiable answer.