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-71870

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

Amit Schendel
Amit Schendel
Senior Security Researcher

Aug 7, 2026·7 min read·3 visits

Executive Summary (TL;DR)

A vulnerability in pypdf allows attackers to trigger a Denial of Service (OOM crash) via crafted /ToUnicode CMap streams containing massive hex-encoded tokens.

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.

Vulnerability Overview

The pypdf library is a widely deployed pure-Python library utilized for parsing, manipulating, and extracting text from PDF documents. A core feature of this library is text extraction, which translates internal PDF character codes into standardized Unicode glyphs. This translation relies heavily on decoding /ToUnicode character map (CMap) streams embedded within font descriptors. These streams define how custom or non-standard encodings map to the Unicode coordinate space.

The vulnerability, designated as CVE-2026-71870, is classified under CWE-400 (Uncontrolled Resource Consumption). The vulnerability is localized in the CMap parsing routines of the library, specifically within the handling of space-separated tokens in bfrange definitions. When processing untrusted files, the library fails to validate or restrict the byte length of tokens parsed from these streams.

This lack of restriction exposes any service running pypdf to resource exhaustion. Exposed applications typically include automated document indexing platforms, email attachment scanners, search engine crawlers, and optical character recognition (OCR) preprocessors. An attacker can craft a document that, when indexed or parsed, consumes all available system memory, leading to a process-level Out-of-Memory (OOM) event and triggering a denial-of-service condition.

Root Cause Analysis

The root cause of CVE-2026-71870 lies within the parsing loop of /ToUnicode CMap streams, specifically inside the parse_bfrange function located in pypdf/_cmap.py. A standard CMap definition maps ranges of character codes to destinations using blocks defined by the beginbfrange and endbfrange operators. The parser reads these blocks sequentially and splits entries into tokens using space character delimiters.

In vulnerable versions of pypdf (prior to 6.15.0), the parser processes these string tokens dynamically using operations like unhexlify and string interpolation without validating token length. An attacker can inject an arbitrarily long hexadecimal string enclosed in angle brackets (such as <4141...41>) within a bfrange block. Because the library performs multi-line parsing and processes every element of the split line, it attempts to load, decode, and map these extremely long sequences.

During processing, pypdf attempts to decode the token using the utf-16-be or charmap codecs and stores the mapping in an internal dictionary (map_dict). Python dictionaries incur memory overhead for each key-value pair, and handling multi-megabyte string objects during runtime dramatically increases heap size. A crafted document under 100 KB in size can trigger allocation pools in the gigabyte range, causing rapid exhaustion of the virtual memory space.

Code Analysis

The vulnerability is localized within pypdf/_cmap.py. In affected versions, the parsing implementation for parse_bfrange extracts parameters from lines directly, splitting on byte-level spaces. Below is the vulnerable parsing code path:

# Affected code path in pypdf/_cmap.py prior to 6.15.0
lst = [x for x in line.split(b" ") if x]
a = int(lst[0], 16)
b = int(lst[1], 16)
...
# Unbounded byte manipulation and mapping assignment
map_dict[unicode_key] = unhexlify(sq).decode("utf-16-be", "surrogatepass")

The patch implemented in commit afba8080e19d29a3c256a742b340995e695b35aa addresses the lack of bounds enforcement by introducing a validation utility and strictly defined byte limits. Because hexadecimal representation doubles the required characters, the token limits are defined as double the maximum byte count:

# Patched limits and validation helper in pypdf/_cmap.py
MAX_CMAP_CODE_BYTES = 8
MAX_CMAP_STRING_BYTES = 512
MAX_CMAP_CODE_BYTES_LIMIT = MAX_CMAP_CODE_BYTES * 2
MAX_CMAP_STRING_BYTES_LIMIT = MAX_CMAP_STRING_BYTES * 2
 
def _check_token_length(token: bytes, limit: int) -> None:
    token_length = len(token)
    if token_length > limit:
        description = {
            MAX_CMAP_CODE_BYTES_LIMIT: "code",
            MAX_CMAP_STRING_BYTES_LIMIT: "string",
        }.get(limit, "token")
 
        raise LimitReachedError(
            f"Maximum /ToUnicode {description} length exceeded: {token_length} > {limit}."
        )

The validation checks are embedded into each critical stage of the parse_bfrange loop, assessing code-length parameters (checked against MAX_CMAP_CODE_BYTES_LIMIT) and multi-byte destination strings (checked against MAX_CMAP_STRING_BYTES_LIMIT):

# Code-level insertion of token validation inside parse_bfrange
if multiline_rg is not None:
    for sq in lst[3:]:
        if sq == b"]":
            break
        _check_token_length(sq, limit=MAX_CMAP_STRING_BYTES_LIMIT)
else:
    _check_token_length(lst[0], limit=MAX_CMAP_CODE_BYTES_LIMIT)
    _check_token_length(lst[1], limit=MAX_CMAP_CODE_BYTES_LIMIT)
    if lst[2] == b"[":
        for sq in lst[3:]:
            if sq == b"]":
                break
            _check_token_length(sq, limit=MAX_CMAP_STRING_BYTES_LIMIT)
    else:
        _check_token_length(lst[2], limit=MAX_CMAP_STRING_BYTES_LIMIT)

Exploitation Methodology

To exploit this vulnerability, an attacker constructs a PDF document containing a font descriptor object with a crafted /ToUnicode mapping. The stream within this mapping contains a bfrange block that defines mappings using abnormally long sequences of hexadecimal characters inside the < and > delimiters.

An example configuration of an payload block within the CMap stream is structured as follows:

/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def
/AMapName /Unicode def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
1 beginbfrange
<0000> <0001> <4141414141414141...[repeated 100000 times]...4141>
endbfrange
endcmap
CMapName currentdict /CMap defineresource pop
end
end

The target application processes this stream during standard operations that invoke text extraction. For example, if a developer writes an automation script to index uploaded resumes or documents, the execution of the following Python block triggers the vulnerability:

from pypdf import PdfReader
 
# Opening and parsing the malicious file structure
reader = PdfReader("malicious.pdf")
for page in reader.pages:
    # This call parses the ToUnicode stream and exhausts memory
    extracted_text = page.extract_text() 

Because the parsing occurs synchronously within the application thread, the interpreter process dynamically inflates in heap size until the kernel's Out-Of-Memory (OOM) killer or the runtime manager terminates the process. No authentication or privileged session is required to trigger this crash.

Impact Assessment

The impact of CVE-2026-71870 is confined to service availability. Because this is an uncontrolled resource consumption issue (CWE-400), it does not directly allow remote code execution (RCE) or unauthorized data exposure. However, it can disrupt production pipelines and microservices responsible for parsing incoming documents.

In cloud native or containerized environments, a crash of the document processing worker will cause container orchestration systems (like Kubernetes) to initiate a restart sequence. If the application pulls files from a queue and repeatedly attempts to parse the same malicious file upon restarting, the service can enter a continuous crash loop. This condition leads to queue starvation and broader system instability.

The CVSS v4.0 base score is calculated at 4.8 (Medium), with the vector 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. This score reflects a local attack vector (as the file must be processed by the local host) with low overall availability impact under standard scoring models, though the operational impact in multi-tenant SaaS platforms can be significant.

Remediation & Strategic Mitigations

The primary remediation strategy is upgrading the pypdf dependency to version 6.15.0 or later. This version enforces maximum limits on /ToUnicode token inputs and throws a LimitReachedError when encountering structured anomalies, preventing memory exhaustion.

pip install --upgrade pypdf>=6.15.0

For environments where immediate upgrading is not possible, defensive engineers should apply sandboxing and process-level resource constraints. Applications handling PDF processing should isolate parser execution to worker nodes configured with memory limits using control groups (cgroups) or container-level specifications. Setting a hard memory limit ensures that a crash in a parser thread is isolated and does not affect the host node.

Furthermore, security audits should note a potential research gap in the fix. The current implementation strictly monitors token lengths in parse_bfrange. However, other CMap mapping structures, such as bfchar mappings (which translate single character codes), may remain unvalidated if they rely on a different code path inside _cmap.py. Security teams should monitor modifications to the library and apply validation layers globally on incoming stream sizes before handing them to the parser library.

Official Patches

py-pdfOfficial GitHub Security Advisory
py-pdfPull Request #3944 addressing CMap limits
py-pdfFix Commit implementing _check_token_length

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

pypdf library deployments processing untrusted PDF documents

Affected Versions Detail

Product
Affected Versions
Fixed Version
pypdf
py-pdf
< 6.15.06.15.0
AttributeDetail
CWE IDCWE-400
Attack VectorLocal (via crafted document parsing)
CVSS Score4.8
ImpactDenial of Service (OOM Process Crash)
Exploit StatusProof-of-Concept only
KEV StatusNot listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-400
Uncontrolled Resource Consumption

The product does not properly control the allocation and maintenance of a limited resource, enabling an actor to influence the amount of resources consumed and eventually leading to exhaustion.

Known Exploits & Detection

GHSA-fp3f-mc75-235cGHSA advisory describing proof of concept and mapping mechanics of oversized /ToUnicode strings.

Vulnerability Timeline

Patch commit afba8080e19d29a3c256a742b340995e695b35aa merged
2026-08-06
pypdf version 6.15.0 released
2026-08-07
CVE-2026-71870 published
2026-08-07

References & Sources

  • [1]GHSA Security Advisory
  • [2]Pull Request #3944
  • [3]Fix Commit
  • [4]Release Information

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

•5 minutes ago•CVE-2026-71851
9.0

CVE-2026-71851: Use of Cryptographically Weak PRNG in crypto-js (Ill Bloom)

A severe, twelve-year-old cryptographic weakness in crypto-js (versions < 4.0.0) generated pseudorandom numbers using a custom Multiply-With-Carry (MWC) algorithm seeded from the non-secure Math.random(). This reduces 128-bit and 256-bit key spaces to just 2^39 and 2^47 possibilities, allowing offline brute-force attacks.

Alon Barad
Alon Barad
0 views•7 min read
•about 2 hours ago•CVE-2026-71852
4.8

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

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.

Amit Schendel
Amit Schendel
6 views•7 min read
•about 3 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
6 views•5 min read
•about 4 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
4 views•6 min read
•about 5 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
6 views•8 min read
•about 6 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
4 views•6 min read