CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-71852

CVE-2026-71852: Denial of Service via Excessive Iteration and Memory Exhaustion in pypdf CID Font Parsing

Amit Schendel
Amit Schendel
Senior Security Researcher

Aug 7, 2026·7 min read·3 visits

Executive Summary (TL;DR)

Unconstrained CID font width expansion in pypdf leads to application hang and OOM crashes.

A Denial of Service (DoS) vulnerability exists in pypdf prior to version 6.15.0. When parsing maliciously crafted PDF files containing excessively large CID font width ranges, the library suffers from CPU starvation and memory exhaustion due to unconstrained loop expansion.

Vulnerability Overview

The library pypdf is a widely utilized open-source Python library for parsing, manipulating, and extracting content from PDF documents. It serves as a foundational component in numerous document-processing pipelines, search indexing systems, and data extraction backends. Because it processes complex, nested binary structures defined by untrusted external users, its parsing functions represent a significant attack surface.

This vulnerability, tracked as CVE-2026-71852, belongs to the class of CWE-834: Excessive Iteration. It resides specifically within the CID (Character Identifier) font width parser module, located in pypdf/_font.py. The flaw enables local or remote unauthenticated actors to trigger a denial of service condition.

The attack is executed by embedding a custom Font dictionary containing structurally anomalous CID widths. When the application attempts to process the font dictionaries during typical workflows like text extraction, the parser executes an unconstrained loop. This results in execution delays and memory allocation overhead.

Root Cause Analysis

The primary flaw stems from the implementation of the static method Font._collect_cid_character_widths() in pypdf/_font.py. This method is designed to parse the /W (Widths) array within a DescendantFont dictionary. According to the PDF specification, the /W array specifies character widths to facilitate accurate typographic rendering and text extraction.

The PDF specification defines two formats for width specifications. Format 1 provides a start character index followed by an array of individual glyph widths. Format 2 defines a starting index, an ending index, and a constant width that is applied uniformly across the entire range. In previous versions, the parser handled both formats by instantly expanding these ranges into a flat Python dictionary mapping each individual character index to its defined width.

The vulnerability is triggered because the parsing logic failed to validate the distance between the starting and ending indices. When encountering a Format 2 entry such as [ 1 200000000 120 ], the parser initializes a generator expression via the Python range() constructor spanning from 1 to 200,000,000. It then processes this range within a dictionary comprehension to populate the internal mapping. This design assumes all inputs are structurally valid and conform to reasonable bounds.

Due to the internal implementation of Python dictionary objects, which use hash tables, allocating millions of keys instantly consumes significant memory resources. The host operating system running the document processing service experiences memory exhaustion, resulting in an OOM termination. If the system has sufficient swap space to prevent an immediate crash, the CPU becomes completely occupied by the iteration, resulting in resource starvation.

Code Analysis

The vulnerability was remediated in the py-pdf/pypdf repository via commit 51cb6acf9e8a35b77e90b4d87d28fe3e1416d7d7. The changes isolate the unconstrained range expansion by implementing defensive thresholds based on the limits of standard typography.

Below is a comparison highlighting the critical code paths before and after the remediation was applied.

Pre-Patch Implementation (Vulnerable)

The following block shows the unvalidated dictionary updates for both format types:

# Format 1: Individual character widths mapping
# If len(width_list) is unchecked, it can trigger high loop counts.
current_widths.update(
    {
        chr(_cidx): _width
        for _cidx, _width in zip(
            range(
                cast(int, start_idx),
                cast(int, start_idx) + len(width_list),
                1,
            ),
            width_list,
        )
    }
)
 
# Format 2: Constant width range mapping
# High stop_idx values lead to excessive iteration.
current_widths.update(
    {
        chr(_cidx): const_width
        for _cidx in range(
            cast(int, start_idx), cast(int, stop_idx + 1), 1
        )
    }
)

Post-Patch Implementation (Remediated)

The patch defines strict structural limits to restrict range bounds to standard typographic constraints:

# Global constraints added to pypdf/_font.py
MAX_CID_WIDTH_ENTRY_COUNT = 65_536  # Standard limit for 16-bit CID spaces
MAX_WIDTH_ENTRY_COUNT = 100_000
 
@staticmethod
def __check_range_length(start: int, end: int) -> None:
    if end < start:
        raise LimitReachedError(
            f"Invalid CID width range: {start}..{end}."
        )
 
    count = end - start
    if count > MAX_CID_WIDTH_ENTRY_COUNT:
        raise LimitReachedError(f"CID width range too large: {count} > {MAX_CID_WIDTH_ENTRY_COUNT}.")
 
@staticmethod
def __check_entry_count(count: int) -> None:
    if count > MAX_WIDTH_ENTRY_COUNT:
        raise LimitReachedError(f"Too many character widths: {count} > {MAX_WIDTH_ENTRY_COUNT}.")

During execution, these functions assert limits prior to dictionary generation:

# Format 1 with range validation
start_idx, width_list = int(w_entry), w_next_entry
stop_idx = start_idx + len(width_list)
Font.__check_range_length(start_idx, stop_idx)
entry_count += (stop_idx - start_idx)
Font.__check_entry_count(entry_count)
 
# Format 2 with range validation
start_idx, stop_idx, const_width = (
    int(w_entry),
    int(w_next_entry),
    _w[idx + 2].get_object(),
)
Font.__check_range_length(start_idx, stop_idx + 1)
entry_count += (stop_idx - start_idx + 1)
Font.__check_entry_count(entry_count)

By asserting these limits, the software prevents the execution of large loops and blocks memory allocations that exceed predefined structural norms.

Exploitation Methodology

Exploitation of CVE-2026-71852 relies on creating a structural PDF file containing abnormal CID metrics within a descendant font object. Since the library processes font resources automatically when analyzing PDF pages, an attacker does not require special administrative access.

The attack path is visualized in the diagram below:

To configure a test case, an attacker creates a DescendantFont dictionary containing a /W array containing a large index span:

3 0 obj
<<
  /Type /Font
  /Subtype /CIDFontType2
  /BaseFont /CustomCIDFont
  /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >>
  /W [ 0 100000000 1000 ]
>>
endobj

When this file is parsed via PdfReader('malicious.pdf') and any method attempting to parse page text is called, the library executes _collect_cid_character_widths(). The processing loop triggers CPU utilization and memory expansion, crashing the active process.

Impact Assessment

The primary impact of CVE-2026-71852 is localized Denial of Service (DoS). When a vulnerable application processes a crafted document, the Python engine allocates memory dynamically to accommodate the generated dictionary. This quickly exhausts system memory, triggering operating system-level process termination via the Out-of-Memory (OOM) killer.

In environments where auto-restart mechanisms are not configured, this termination results in a persistent denial of service state. For backend systems processing documents asynchronously (e.g., through a queue), the crash of worker processes can stall the entire pipeline, as the offending document is repeatedly picked up and re-processed.

The vulnerability is rated at a CVSS score of 4.8. Although the attack vector is local, the actual mechanism of delivery is frequently remote, such as uploading a file to a web application. Consequently, document processing utilities facing public-facing endpoints represent the primary area of exposure.

Remediation and Mitigation

The primary remediation strategy is upgrading the pypdf dependency to version 6.15.0 or higher. The maintainers resolved the issue by introducing the input size and bounds checks documented in commit 51cb6acf9e8a35b77e90b4d87d28fe3e1416d7d7.

To execute the upgrade via standard package managers, run the following command:

pip install --upgrade pypdf>=6.15.0

Where immediate upgrade is unfeasible, implement host-level resource constraints. Configure container limits inside runtime environments to prevent a single parsing thread from affecting surrounding system services:

# Example docker-compose resource limits
services:
  pdf-worker:
    image: pdf-processor:latest
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M

Additionally, apply maximum payload size constraints on incoming files to minimize resource footprint and restrict document processing execution time through application-level timeouts.

Patch Security Assessment & Potential Bypasses

An analysis of the remediation commit reveals potential security boundaries that developers and security administrators should monitor. The patch enforces the limits using a local counter variable, entry_count, which tracking elements during a single call to _collect_cid_character_widths().

Because the counter is initialized to 0 at the start of the function call, it does not maintain state across multiple font dictionary processing operations. If a document defines multiple /DescendantFonts in a single complex font resource, pypdf iterates over each descendant font sequentially. Each descendant font can populate up to 100,000 entries into the shared character_widths dictionary reference.

This design permits an attacker to define dozens of child font dictionaries, each carrying slightly less than the 100,000 limit. When merged, the final character_widths mapping can still reach dimensions that cause significant memory growth. Furthermore, developers should inspect equivalent mapping modules, such as vertical typographic specifications (/W2) and custom CMaps, to confirm that range expansions are subject to similar validations.

Fix Analysis (1)

Technical Appendix

CVSS Score
4.8/ 10
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N

Affected Systems

Any Python application or backend service utilizing pypdf versions prior to 6.15.0 to extract text, parse metadata, or merge PDF documents.

Affected Versions Detail

Product
Affected Versions
Fixed Version
pypdf
py-pdf
< 6.15.06.15.0
AttributeDetail
CWE IDCWE-834
Attack VectorLocal
CVSS v4.04.8
ImpactDenial of Service (DoS)
Exploit Statusnone
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-834
Excessive Iteration

The software does not limit the number of times a loop or iteration can execute, allowing excessive resource consumption.

Vulnerability Timeline

Fix commit pushed to repository
2026-08-06
GitHub Security Advisory published
2026-08-07
CVE-2026-71852 assigned and published
2026-08-07
Version 6.15.0 released with complete remediation
2026-08-07

References & Sources

  • [1]https://github.com/py-pdf/pypdf/security/advisories/GHSA-fwg2-594c-jp42
  • [2]https://github.com/py-pdf/pypdf/pull/3946
  • [3]https://github.com/py-pdf/pypdf/commit/51cb6acf9e8a35b77e90b4d87d28fe3e1416d7d7
  • [4]https://github.com/py-pdf/pypdf/releases/tag/6.15.0
  • [5]https://www.cve.org/CVERecord?id=CVE-2026-71852

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•12 minutes ago•CVE-2026-71870
4.8

CVE-2026-71870: Uncontrolled Resource Consumption (DoS) in pypdf ToUnicode CMap Parsing

An uncontrolled resource consumption vulnerability (CWE-400) exists in pypdf prior to version 6.15.0. When extracting text from a specially crafted PDF document, the parser fails to restrict token lengths within /ToUnicode CMap streams, causing unbounded memory allocation and process termination via Out-of-Memory (OOM) crashes.

Amit Schendel
Amit Schendel
0 views•7 min read
•about 2 hours ago•CVE-2026-56818
6.5

CVE-2026-56818: Denial of Service via Memory Pinning in Netty Redis Array Aggregator

A vulnerability in Netty's Redis codec allows remote unauthenticated attackers to cause a memory-pinning Denial of Service (DoS) due to the failure to release partial aggregate state when specific error conditions occur in RedisArrayAggregator. When processing Redis Serialization Protocol (RESP) messages, the aggregator fails to clear internal queues and release retained direct byte buffers on exception paths triggered by exceeded maxElements or invalid length properties. If the pipeline does not explicitly tear down the connection upon detecting a decoder error, subsequent elements continue utilizing the stale context, allowing memory blocks to remain indefinitely pinned.

Amit Schendel
Amit Schendel
2 views•5 min read
•about 3 hours ago•CVE-2026-54164
6.5

CVE-2026-54164: Missing IRI Type Validation in API Platform Core Enables Resource Type Confusion

CVE-2026-54164 is a class/type confusion vulnerability (CWE-843) in API Platform Core. When processing relationships via Internationalized Resource Identifiers (IRIs) in write requests, the framework's normalizer fails to verify if the resolved resource matches the expected type. For PHP applications utilizing untyped properties, the mismatched object is silently assigned, breaking domain logic and data integrity.

Alon Barad
Alon Barad
2 views•6 min read
•about 4 hours ago•GHSA-WVPP-8HX9-P66J
9.8

GHSA-WVPP-8HX9-P66J: Arbitrary Command Execution via Option Guard Bypass in GitPython

An unsafe option guard bypass vulnerability exists in GitPython before version 3.1.58. When keyword arguments are passed to Git commands with split_single_char_options=False, GitPython's argument validation helper fails to inspect the combined short-option value. This discrepancy allows short-option token smuggling or clustering manipulation, enabling remote attackers to bypass option blocklists and execute arbitrary system commands.

Alon Barad
Alon Barad
4 views•8 min read
•about 5 hours ago•GHSA-WG23-69C2-GJC8
9.1

GHSA-WG23-69C2-GJC8: Passkey Login Replay Vulnerability in Craft CMS

GHSA-WG23-69C2-GJC8 is a critical security vulnerability discovered in the native Passkey (WebAuthn) login implementation of Craft CMS. The vulnerability allows an attacker to bypass WebAuthn's core cryptographic challenge-response and signature-counter replay protections. By intercepting a single successful passkey login request body, an attacker can replay the identical request payload to generate additional authenticated active sessions, resulting in complete account takeover.

Alon Barad
Alon Barad
2 views•6 min read
•about 6 hours ago•GHSA-JFM3-95JQ-Q3RF
7.5

GHSA-jfm3-95jq-q3rf: Algorithmic Complexity Denial of Service and Path-Delimiter Injection in league/commonmark Footnote Extension

An architectural flaw in the Footnote extension of league/commonmark allows unauthenticated remote attackers to trigger severe denial of service conditions through algorithmic complexity exploitation (O(N^2) CPU and memory exhaustion) and path-delimiter injection leading to unexpected application-level crashes.

Alon Barad
Alon Barad
2 views•8 min read