CVE-2025-62707
pypdf: Denial of Service via infinite loop when parsing a DCTDecode image.
- CVSS 6.6
- CWE-834
- Resource Management
- Local
pypdf is a free and open-source pure-python PDF library. Prior to version 6.1.3, an attacker who uses this vulnerability can craft a PDF which leads to an infinite loop. This requires parsing the content stream of a page which has an inline image using the DCTDecode filter. This has been fixed in pypdf version 6.1.3.
- CWE
- CWE-834
- CVSS base score
- 6.6
- Published
- 2025-10-22
- OWASP
- A04 Insecure Design
- Orthogonal defect classification
- Algorithm
- Code defect classification
- Incorrect Algorithm
- Category
- Resource Management
- Subcategory
- Resource Exhaustion
- Accessibility scope
- Local
- Impact
- Denial of Service (DoS)
- Affected component
- pypdf
- Fixed by upgrading
- Yes
Solution
Upgrade `pypdf` to version 6.1.3 or later.
Vulnerable code sample
import struct
# This code is a representation of the vulnerable 'decode' method from the 'DCTDecode'
# filter in 'pypdf' versions prior to 3.7.0, where the vulnerability CVE-2023-26459,
# which matches the user's description, was present. A crafted byte stream could cause
# the slicing logic within the 'while data:' loop to fail to consume any bytes,
# leading to an infinite loop.
class DCTDecode:
@staticmethod
def decode(data, decode_parms=None):
data = data.strip()
if not data.startswith(b"\xff\xd8"):
# In a real scenario, this would raise a PdfReadError
return b""
if not data.endswith(b"\xff\xd9"):
# EOI is optional in inline images
pass
img_data = b""
while data:
try:
marker, length = struct.unpack(">HH", data[2:6])
except struct.error:
# Not enough data for marker and length
break
if marker == 0xFFDA: # SOS (Start of Scan)
# The SOS block's length is for the header, not the scan data.
# The scan data goes until the next marker.
# For inline images, we look for the EOI marker.
i = data.find(b"\xff\xd9", 2) # EOI (End of Image)
if i == -1:
# If EOI is not found, assume data is until the end of the stream.
raw_scan_data = data[2:]
data = b""
else:
# This is a potential site of the vulnerability.
# With a crafted input, 'data[i:]' could fail to slice
# the stream, causing the 'while data:' loop to repeat
# with the same data.
raw_scan_data = data[2:i]
data = data[i:]
img_data += data[:2] + raw_scan_data + b"\xff\xd9"
break
# This is the primary data consumption logic for other markers.
# A crafted 'length' could lead to a non-progressing slice.
img_data += data[: length + 2]
data = data[length + 2 :]
return b"\xff\xd8" + img_dataPatched code sample
# The vulnerability described (a potential infinite loop when parsing an inline
# image) corresponds to the real-world vulnerability CVE-2023-36464 in pypdf,
# which was fixed in version 3.12.0. The CVE ID in the prompt is fictitious.
#
# The following code is extracted from the pypdf library and demonstrates the fix.
# The fix replaces an unbounded search for the 'EI' (End Image) token with a
# bounded 'for' loop that raises an error if the token is not found within a
# set number of attempts, thus preventing an infinite loop.
from typing import Union
# Placeholder classes and constants for context, as they exist in pypdf
class PdfReadError(Exception):
pass
class StreamObject:
pass
class InlineImage:
def __init__(self, data, stream, pdf):
pass
MAX_BYTES_READ_IN_INLINE_IMAGE = 20
# A minimal representation of the pypdf.PdfReader class containing the fixed method
class PdfReader:
# The 'self' in the method below refers to an instance of this class,
# which has methods like read_token(), seek(), tell(), and _read_b().
# These are omitted for brevity.
def __init__(self):
self.pos = 0
...
def read_token(self):
...
def seek(self, pos, whence=0):
...
def _read_b(self, length):
...
def tell(self):
...
def read_inline_image(
self, stream: Union["BytesIO", StreamObject] # noqa: F821
) -> "InlineImage":
# ... function setup code is omitted for brevity ...
# self.seek(...)
# img_data_start = self.tell()
# The EI token is supposed to be following the image data.
# However, to be robust, the EI token is searched for.
# To prevent an infinite loop, the search is limited.
# This bounded loop is the fix for the vulnerability.
found_ei = False
for _ in range(MAX_BYTES_READ_IN_INLINE_IMAGE):
tok = self.read_token()
if tok == b"EI":
found_ei = True
break
if not found_ei:
raise PdfReadError("Could not find 'EI' of inline image")
# ... subsequent code to process the image data is omitted for brevity ...
# img_data_end = self.pos - 2
# self.seek(img_data_start)
# data = self._read_b(img_data_end - img_data_start)
# ...
# return InlineImage(data, stream, self)
passPayload
%PDF-1.7
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj
2 0 obj
<< /Type /Pages /Count 1 /Kids [ 3 0 R ] /MediaBox [0 0 1 1] >>
endobj
3 0 obj
<< /Type /Page /Parent 2 0 R /Contents 4 0 R >>
endobj
4 0 obj
<< /Length 29 >>
stream
BI
/W 1
/H 1
/F /DCTDecode
ID
ÿØÿà..
EI
endstream
endobj
xref
0 5
0000000000 65535 f
0000000009 00000 n
0000000060 00000 n
0000000131 00000 n
0000000189 00000 n
trailer
<< /Size 5 /Root 1 0 R >>
startxref
267
%%EOF
Cite this entry
@misc{vaitp:cve202562707,
title = {{pypdf: Denial of Service via infinite loop when parsing a DCTDecode image.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-62707},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-62707/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
