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



GHSA-MH25-X5HQ-WRQP

GHSA-MH25-X5HQ-WRQP: Algorithmic Complexity Denial of Service in league/commonmark UniqueSlugNormalizer

Alon Barad
Alon Barad
Software Engineer

Aug 7, 2026·6 min read·10 visits

Executive Summary (TL;DR)

A quadratic complexity flaw in league/commonmark's heading slug generator allows remote attackers to exhaust server CPU and trigger a total Denial of Service by submitting Markdown documents with thousands of identical headings.

An algorithmic complexity vulnerability in the UniqueSlugNormalizer component of the league/commonmark PHP library allows unauthenticated remote attackers to trigger severe CPU resource consumption and Denial of Service (DoS) by submitting a Markdown document containing a high volume of duplicate headings. The slug generation loop resets its sequential search index back to 1 for every collision, resulting in a quadratic execution path. This flaw affects versions from 2.0.0-beta1 up to and including 2.8.3, and is patched in version 2.9.0.

Vulnerability Overview

The league/commonmark package is a highly popular, extensible PHP Markdown parser that fully supports the CommonMark and GitHub Flavored Markdown (GFM) specifications. Within modern web applications, it is standard practice to enable heading anchors using extensions like the HeadingPermalinkExtension. This component relies on the UniqueSlugNormalizer to transform heading text into readable, unique identifiers for HTML anchor linking.

When multiple headings within a single document produce the same initial slug, the normalizer appends a sequential numeric suffix to guarantee uniqueness (e.g., # Heading becomes heading, the second becomes heading-1, and the third becomes heading-2). This mechanism is critical for ensuring page navigation and structural integrity of parsed HTML documents.

However, in all versions of the library from 2.0.0-beta1 up to and including 2.8.3, the unique slug generation engine contains an algorithmic complexity flaw. Specifically, when processing a document with a massive sequence of duplicate headings, the CPU time required to generate unique identifiers escalates quadratically ($O(N^2)$). This flaw allows unauthenticated remote attackers to trigger severe CPU resource consumption, leading to a complete Denial of Service.

Root Cause Analysis

To understand the core algorithmic vulnerability, we must examine how the UniqueSlugNormalizer tracks and resolves slug collisions. The normalizer maintains an internal tracking array named $alreadyUsed to keep track of every slug that has already been generated within the current parsing context. In the vulnerable versions, this array maps the slug string to a simple boolean value (array<string, bool>).

When a new heading is parsed, the engine normalizes the text to create a base slug. If this base slug already exists in the $alreadyUsed array, the normalizer enters a do-while loop to find a unique suffix. Crucially, the loop resets the suffix search index to 0 and increments it by 1 on every single collision, sequentially checking if $normalized-$suffix is present in the tracking array.

For the $N$-th identical heading in a document, the normalizer must sequentially verify that $normalized-1, $normalized-2, ..., $normalized-(N-1) are all occupied before it can conclude that $normalized-N is free. This linear search inside a loop results in a classic quadratic complexity flaw. The total number of array lookups required for $N$ identical headers is calculated as $\frac{N(N + 1)}{2}$. For example, a document containing 10,000 duplicate headers requires approximately 50 million array lookups and string interpolations, exhausting server CPU capacity.

Code Analysis

Evaluating the code-level changes between v2.8.3 and v2.9.0 highlights the exact mechanism of the flaw and the patch. In the vulnerable version, the loop repeatedly calls \array_key_exists starting from zero:

// Vulnerable Implementation in v2.8.3 and lower
if (\array_key_exists($normalized, $this->alreadyUsed)) {
    $suffix = 0;
    do {
        ++$suffix;
    } while (\array_key_exists("$normalized-$suffix", $this->alreadyUsed));
 
    $normalized = "$normalized-$suffix";
}
$this->alreadyUsed[$normalized] = true;

The patch in version v2.9.0 completely restructures this tracking logic. Instead of mapping slugs to boolean values, the $alreadyUsed array now maps each base slug to the next numeric suffix to try as an integer (array<string, int>).

// Patched Implementation in v2.9.0
if (isset($this->alreadyUsed[$normalized])) {
    $suffix = $this->alreadyUsed[$normalized];
    while (isset($this->alreadyUsed["$normalized-$suffix"])) {
        ++$suffix;
    }
 
    $this->alreadyUsed[$normalized] = $suffix + 1;
    $normalized = "$normalized-$suffix";
}
$this->alreadyUsed[$normalized] = 1;

By tracking the last used suffix in the state array, the normalizer avoids checking previously assigned indices. It directly fetches the cached next suffix, reducing the lookups from a quadratic $O(N^2)$ to a linear $O(N)$ overall complexity. This fix is complete and robust against variant attacks because it ensures that subsequent lookups bypass the occupied suffix range entirely.

Exploitation Methodology

Exploiting this vulnerability does not require complex tooling, authorization, or specific network positioning. The only prerequisite is a web application endpoint that parses user-supplied Markdown content using league/commonmark with heading anchor links or permalinks enabled. This scenario is highly common on wiki pages, blog comment sections, ticket systems, and public forums.

An attacker executes the attack by compiling a Markdown document composed of a large number of duplicate headings. A typical payload contains thousands of identical heading elements:

# duplicate
# duplicate
# duplicate
# duplicate
# duplicate
... [repeated 10,000 times] ...

When the attacker submits this payload via an HTTP POST request, the PHP parser thread attempts to resolve the unique slugs for all 10,000 headers. This triggers millions of iterations of the internal loop, locking the corresponding PHP-FPM or CGI process at 100% CPU utilization. Because standard web server configurations limit the number of simultaneous PHP worker processes, sending a few parallel requests with this payload completely depletes the worker pool, causing a total Denial of Service for all legitimate users.

Impact Assessment

The concrete security impact of this vulnerability is a high-severity Denial of Service (DoS). While the vulnerability does not expose sensitive data, alter database records, or facilitate remote code execution, it represents a highly effective vector for disrupting application availability with minimal effort.

From a CVSS v3.1 perspective, we assess this vulnerability at a score of 7.5 (High), with the vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. This reflects that the attack can be launched over the network without authentication or user interaction, and results in a high availability impact.

In standard PHP hosting architectures, worker pools are shared across the entire web application. When an attacker exhausts the worker threads by submitting colliding heading payloads, the entire web server is rendered incapable of serving other static or dynamic requests. This results in broad downtime, rendering the application completely offline until the hung worker processes are terminated or the web server is restarted.

Remediation & Mitigation Guidance

The primary and recommended remediation is to upgrade league/commonmark to version v2.9.0 or higher. This version implements the optimized $alreadyUsed tracking index that completely eliminates the quadratic execution complexity.

composer update league/commonmark

For organizations that cannot immediately apply the patch, several effective mitigation options exist. The first option is to disable the HeadingPermalinkExtension if unique anchor links are not strictly necessary for the application's layout. This stops the vulnerable normalizer code path from executing entirely.

// Disable HeadingPermalinkExtension in your Markdown Environment configuration
// $environment->addExtension(new HeadingPermalinkExtension());

Additionally, applications should implement input validation controls. Setting a reasonable limit on the overall length of user-submitted Markdown or restricting the maximum number of headings allowed in a single request protects the parser from handling excessively large or malicious structures. Setting a strict max_execution_time in PHP's configuration also ensures hung threads are killed before they exhaust the server's thread pool.

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Affected Systems

league/commonmark

Affected Versions Detail

Product
Affected Versions
Fixed Version
league/commonmark
thephpleague
>= 2.0.0-beta1, <= 2.8.32.9.0
AttributeDetail
CWE IDCWE-400 (Uncontrolled Resource Consumption)
Attack VectorNetwork / Unauthenticated
CVSS v3.1 Score7.5 (High)
Exploit StatusProof-of-Concept (PoC) Available
Vulnerability ClassAlgorithmic Complexity / Denial of Service
Affected ComponentUniqueSlugNormalizer

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, eventually leading to the exhaustion of available resources.

Vulnerability Timeline

Vulnerability patched and advisory GHSA-MH25-X5HQ-WRQP published
2026-08-03

References & Sources

  • [1]GitHub Security Advisory GHSA-MH25-X5HQ-WRQP
  • [2]league/commonmark v2.9.0 Release Notes
  • [3]league/commonmark Changelog
  • [4]Patched UniqueSlugNormalizer Source
  • [5]Vulnerable UniqueSlugNormalizer Source

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

•18 minutes ago•CVE-2026-105749
6.5

CVE-2026-105749: Unbounded Table Attributes in Docling Backends Leads to Resource Exhaustion

An uncontrolled resource consumption vulnerability exists in the Docling document conversion library. Maliciously structured HTML, JATS, ODS, or BoxNote inputs containing table cells with excessively large 'rowspan' or 'colspan' attribute values trigger algorithmic complexity conditions. This allows unauthenticated remote attackers to initiate resource exhaustion states, crashing or hanging the target document processing pipeline while bypassing configured timeouts.

Amit Schendel
Amit Schendel
0 views•6 min read
•about 1 hour ago•CVE-2026-105748
4.3

CVE-2026-105748: Local File Inclusion and Arbitrary File Disclosure in Docling Document Parser

A Local File Inclusion (LFI) and Arbitrary File Disclosure vulnerability exists in Docling and Docling Slim versions >= 2.16.0 up to 2.131.0. When parsing serialized DoclingDocument structures using the JSON input format, the backend fails to restrict image URI schemes, allowing remote attackers to retrieve local files and verify path existence on the host system during embedded document export.

Amit Schendel
Amit Schendel
3 views•5 min read
•about 2 hours ago•CVE-2026-105744
7.5

CVE-2026-105744: Arbitrary File Read and Remote Code Execution in Docling Tectonic Engine

Docling, a tool for parsing and processing diverse document formats, is vulnerable to arbitrary file read, arbitrary file write, and potential remote code execution (RCE) in versions 2.94.0 through 2.131.0. The vulnerability occurs when applications configure Docling to use the Tectonic engine for rendering TikZ diagrams into images. Because the compilation did not restrict hazardous TeX primitives or sandbox the environment, an attacker can supply crafted documents containing malicious TikZ definitions to access or modify local files and execute arbitrary commands under the privileges of the processing application.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 3 hours ago•CVE-2026-105743
4.0

CVE-2026-105743: Server-Side Request Forgery Guard Bypass in Docling Document Conversion Engine

An SSRF guard bypass vulnerability in the Docling document conversion engine allows unauthenticated attackers to bypass internal IP access controls. The vulnerability exists due to a DNS rebinding Time-of-Check Time-of-Use (TOCTOU) condition, URL authority parsing inconsistencies, and unvalidated network requests triggered during headless browser page rendering.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 4 hours ago•CVE-2026-105742
3.7

CVE-2026-105742: Sensitive Custom Header Leakage in Docling Image Resource Loader

A technical analysis of CVE-2026-105742 (GHSA-p3fw-7699-7926), a sensitive information disclosure vulnerability in the Docling document processing library. Vulnerable versions of Docling indiscriminately forward custom HTTP headers, such as authentication tokens, to arbitrary third-party origins and during cross-origin redirects while fetching remote image assets from untrusted HTML and EPUB documents.

Alon Barad
Alon Barad
5 views•6 min read
•about 5 hours ago•CVE-2026-106121
4.9

CVE-2026-106121: Denial of Service via Infinite Loop in RabbitMQ Java Client JSON Parser

CVE-2026-106121 is a Denial of Service (DoS) vulnerability in the RabbitMQ Java Client library (amqp-client) affecting versions prior to 5.37.0. The vulnerability resides in the legacy, custom JSON-RPC parsing class com.rabbitmq.tools.json.JSONReader. When parsing malformed or truncated payloads ending within a quoted string or single-line comment, the parser's scanner enters an infinite loop. This occurs because the loop lacks an exit condition for the end-of-input sentinel character returned by the iterator, leading to either CPU exhaustion or a JVM crash from an OutOfMemoryError.

Amit Schendel
Amit Schendel
7 views•6 min read