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·1 visit

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

•39 minutes 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
1 views•6 min read
•about 2 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
1 views•8 min read
•about 4 hours ago•GHSA-MJ63-M3RC-8PPR
5.3

GHSA-MJ63-M3RC-8PPR: Quadratic-Time Complexity in league/commonmark XML Pretty-Printing

A Denial of Service vulnerability exists in the league/commonmark package for PHP when using the XML rendering subsystem. Due to unconstrained indentation based on AST depth, rendering deeply nested elements leads to asymmetric resource consumption (quadratic output size complexity).

Amit Schendel
Amit Schendel
2 views•7 min read
•about 5 hours ago•GHSA-265M-7826-WJQM
8.7

GHSA-265m-7826-wjqm: Authenticated Remote Code Execution in Craft CMS via condition.config JSON Cleanse Bypass

Craft CMS contains an authenticated remote code execution vulnerability due to a sanitization bypass in its search condition configuration parser. An attacker with access to the control panel can inject unsafe Yii2 behavior configurations wrapped inside a JSON-encoded string. When decoded and merged by the application, these keys bypass the global config cleanse filter and are evaluated by the Yii2 component factory, leading to arbitrary code execution.

Alon Barad
Alon Barad
3 views•7 min read
•about 6 hours ago•GHSA-F5WM-88JV-G5HX
8.7

GHSA-F5WM-88JV-G5HX: Authenticated Remote Code Execution via Twig Sandbox Escape in Craft CMS

An authenticated remote code execution vulnerability exists in Craft CMS due to a flaw in how the Twig template sandbox policy handles class-level allowlists. Prior to the fix, the security policy allowed arbitrary public methods from parent classes of allowed interfaces, allowing authenticated attackers to invoke Yii component methods such as attachBehavior on element models to load arbitrary classes and execute system commands.

Alon Barad
Alon Barad
1 views•6 min read
•about 7 hours ago•GHSA-P8X7-9VFW-P7VC
8.8

GHSA-P8X7-9VFW-P7VC: Arbitrary User Password Reset via Mass Assignment in Craft CMS

A high-severity authorization bypass vulnerability in Craft CMS allows authenticated users to reset arbitrary user passwords, including administrator accounts, by exploiting a mass assignment vulnerability in the User element model.

Alon Barad
Alon Barad
2 views•5 min read