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-JFM3-95JQ-Q3RF

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

Alon Barad
Alon Barad
Software Engineer

Aug 7, 2026·8 min read·10 visits

Executive Summary (TL;DR)

Unauthenticated remote attackers can exhaust server memory and CPU resources or crash the PHP worker process by submitting crafted footnote definitions containing duplicate labels or path-delimiting characters.

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.

Vulnerability Overview

league/commonmark is a widely adopted Markdown processing library for PHP. The FootnoteExtension, introduced in version 1.5.0, enables native parsing and rendering of footnotes and their associated backreferences. This extension is typically used in applications accepting rich-text content from users, such as content management systems, blogs, or collaborative portals.

Because the footnote parser processes document structure prior to final HTML generation, it exposes an unauthenticated attack surface to anyone capable of submitting Markdown content. If the extension is enabled, an attacker can exploit structural processing weaknesses to trigger severe denial of service conditions. The issues stem from algorithmic inefficiencies and insecure key-value configuration storage mechanisms inside the parser's event-driven pipeline.

The vulnerability is tracked under GitHub Security Advisory ID GHSA-jfm3-95jq-q3rf. It has a CVSS v3.1 base score of 7.5, reflecting a high-severity impact on system availability. Remediation requires an update to the underlying library or disabling the affected extension altogether.

Root Cause Analysis

The vulnerability consists of two primary logical failures in the Footnote extension parser. The first failure is an algorithmic complexity issue ($O(N^2)$ complexity) located in the interaction between footnote definitions and their backreferences. The second failure is an injection vulnerability resulting from path delimiter parsing inside the library's internal configuration management system.

In the first issue, the parser processes footnote definitions using an event listener called GatherFootnotesListener. Under normal conditions, a single footnote definition maps to one or more references. However, the parser fails to enforce uniqueness constraints on footnote labels. When multiple duplicate footnote definitions exist for the same label, the system processes every duplicate definition block separately and associates each block with all existing backreferences. This creates an $O(M \times N)$ operational multiplier, where $M$ is the number of footnote references and $N$ is the number of duplicate footnote definitions.

In the second issue, the NumberFootnotesListener stores footnote references inside a metadata configuration dictionary managed by $document->data. This data container processes keys containing period (.) or slash (/) characters as nested path delimiters. Because the footnote destination labels are derived directly from user input, an attacker can inject path-delimiter characters. This causes the data manager to interpret literal strings as multidimensional array indices, leading to structural collisions, data mutation, or fatal PHP type mismatches.

Code Analysis

To understand the structural failure, we examine the logic of GatherFootnotesListener and NumberFootnotesListener prior to commit 66028124a17ba193da7b11cc3dfda92df21bfbf4.

In the vulnerable implementation of the footnote accumulator, the iterator iterates over all block nodes without checking if a given footnote label has already been declared. This allows redundant Footnote nodes to remain within the abstract syntax tree. For each node, it creates backreferences repeatedly based on keys stored in the document data:

// Vulnerable implementation of GatherFootnotesListener
foreach ($document->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) {
    if (! $node instanceof Footnote) {
        continue;
    }
    // User-controlled destination label is turned into a configuration lookup key
    $key = '#' . $this->config->get('footnote/footnote_id_prefix') . $node->getReference()->getDestination();
    if ($document->data->has($key)) {
        // Generates backref nodes for each duplicate footnote block
        $this->createBackrefs($node, $document->data->get($key));
    }
}

The corresponding patch addresses this by performing a tracking pass to deduplicate defined footnote labels. The duplicate nodes are cataloged and removed from the syntax tree prior to the generation of backreferences. This reduces the processing complexity from $O(N^2)$ down to a safe linear $O(N)$ execution path.

// Patched implementation of GatherFootnotesListener
$definitions = [];
$discarded   = [];
 
foreach ($document->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) {
    if (! $node instanceof Footnote) {
        continue;
    }
    $label = $node->getReference()->getLabel();
    if (isset($definitions[$label])) {
        // Identify redundant duplicate blocks for removal
        $discarded[] = $node;
        continue;
    }
    $definitions[$label] = $node;
}
 
// Process only unique footnote definitions
foreach ($definitions as $node) {
    $key = '#' . $this->config->get('footnote/footnote_id_prefix') . $node->getReference()->getDestination();
    if (isset($backrefs[$key])) {
        $this->createBackrefs($node, $backrefs[$key]);
    }
}
 
// Detach the duplicate blocks to prevent downstream structural issues
foreach ($discarded as $duplicate) {
    $duplicate->detach();
}

Additionally, the dot-notation path traversal issue in NumberFootnotesListener is resolved. Instead of writing references dynamically using $document->data->append($destination, $reference), the library now aggregates backreferences in a native PHP associative array ($backrefs), which treats delimiters like dot and slash as standard characters. The aggregate array is subsequently stored under a single, secure nested dictionary path.

// Patched reference storage mechanism in NumberFootnotesListener
$backrefs = [];
foreach ($document->iterator() as $node) {
    // ... processes nodes ...
    // Safe insertion into a native PHP associative array instead of dot-notation storage
    $backrefs[$existingReference->getDestination()][] = $newReference;
}
// Write safe structured container to configuration
$document->data->set('footnote/backrefs', $backrefs);

Exploitation & Attack Methodology

Exploitation of the algorithmic complexity vulnerability requires only an unauthenticated HTTP request containing a crafted Markdown body. The attacker does not need special privileges or a specific session state. The target endpoint must parse user-supplied input using the league/commonmark parser with the FootnoteExtension enabled.

To construct an algorithmic complexity exploit payload, an attacker defines a highly repetitive list of footnote references matched with a corresponding block of duplicate footnote definitions. Because the parser attempts to map each reference to every duplicate definition, the payload size scales linearly while execution complexity scales quadratically.

This is a reference[^a] and another[^a] and another[^a] (repeated M times)
 
[^a]: Definition 1
[^a]: Definition 2
[^a]: Definition 3 (repeated N times)

For example, setting $M = 1000$ and $N = 1000$ results in a payload size of approximately 10 kilobytes. Processing this payload forces the parser to allocate more than 440 megabytes of memory and consume over 3 seconds of CPU execution. This exceeds typical default web server limitations, such as the PHP memory_limit of 128MB, triggering an immediate out-of-memory crash of the worker process.

Alternatively, path delimiter injection is triggered by utilizing footnote labels with nested periods. When parsing the document, the internal data manager interprets the dot notation as an array traversal instruction. If the target structure has a different format than expected (such as a string instead of an array), PHP throws a fatal runtime error and halts execution.

[^a] and [^a.b]
 
[^a]: base note
[^a.b]: nested path note

Impact Assessment

The impact of this vulnerability is a high-severity Denial of Service (DoS) affecting the availability of the application server. When a web server processes the malicious Markdown payload, the target PHP process consumes 100% CPU capacity and runs out of allocatable memory. This leads to the termination of the active PHP-FPM worker or Apache child process.

If multiple requests are submitted concurrently, an attacker can easily exhaust the entire pool of available web worker processes. This leaves the server unable to respond to legitimate HTTP traffic, resulting in a persistent offline state for the web application. Because the exploit payload is exceptionally small (approximately 10 KB), standard network-level mitigations such as maximum request size limits are ineffective.

Additionally, the path-delimiter injection flaw allows attackers to reliably crash any PHP script that parses footnote references. Because this error results in a fatal runtime exception, it bypasses standard application-level try-catch handling blocks, preventing graceful degradation or error reporting.

There is no known risk of remote code execution or data exposure associated with this vulnerability. The weakness is categorized strictly under CWE-407 (Inefficient Algorithmic Complexity) and CWE-400 (Uncontrolled Resource Consumption).

Remediation & Mitigation Guidance

The absolute remediation for this vulnerability is to upgrade the league/commonmark library to version 2.9.0 or higher. This release contains the formal patch that deduplicates footnote definitions and replaces the insecure dot-notation storage mechanism.

For environments where an immediate package upgrade is not feasible, the following workarounds can be implemented:

First, disable the FootnoteExtension from the Markdown configuration environment. If the extension is not registered, the parser treats footnote syntax as standard plaintext, completely neutralizing the attack vector.

// Insecure Configuration
$environment->addExtension(new FootnoteExtension());
 
// Mitigated Configuration (Remove the above line entirely)

Second, implement application-level pre-parsing filters. You can use regular expressions to detect duplicate footnote labels or labels containing period or slash characters prior to invoking the league/commonmark compiler. If any invalid or duplicate footnote pattern is detected, the application should reject the input before execution reaches the vulnerable parsing engine.

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 (Composer package, PHP)

Affected Versions Detail

Product
Affected Versions
Fixed Version
league/commonmark
thephpleague
>= 1.5.0, < 2.9.02.9.0
AttributeDetail
CWE IDCWE-407 (Inefficient Algorithmic Complexity)
Attack VectorNetwork (Remote, Unauthenticated)
CVSS v3.1 Score7.5 (High)
Impact TypeDenial of Service (OOM and CPU Exhaustion)
Exploit StatusProof of Concept available
KEV StatusNot listed

MITRE ATT&CK Mapping

T1499.003Endpoint DoS: Application Exhaustion
Impact
CWE-407
Inefficient Algorithmic Complexity

The product or application uses an algorithm or data structure with an inefficient worst-case complexity (such as quadratic O(N^2)) that can be abused by an attacker to consume excessive resources.

Vulnerability Timeline

Vulnerability patched in source repository
2026-08-03
Official package version 2.9.0 released
2026-08-06
GHSA security advisory published
2026-08-06

References & Sources

  • [1]GitHub Advisory Database Entry
  • [2]Vendor Security Advisory
  • [3]Official Patch Commit
  • [4]Release v2.9.0 Changelog

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-78G4-XQWV-Q3G8
7.5

GHSA-78G4-XQWV-Q3G8: Heap-Based Buffer Overflow in Pillow (libopenjp2)

A heap-based buffer overflow vulnerability in Pillow PyPI binary wheels (versions 11.1.0 to 12.x) allows remote code execution or application crash via crafted JPEG 2000 files processed by the bundled libopenjp2 library.

Alon Barad
Alon Barad
4 views•4 min read
•about 2 hours ago•CVE-2026-109618
9.8

CVE-2026-109618: Remote Code Execution in PHP Core via Out-of-Memory longjmp() Uninitialized Memory Access

CVE-2026-109618 (dubbed PHP2Shell) is a critical vulnerability in the PHP engine core resulting from improper out-of-memory exception handling via longjmp(). When request allocation fails mid-processing, non-local control flow bypasses cleanup procedures, leaving memory structures uninitialized or in a use-after-free state during request shutdown.

Amit Schendel
Amit Schendel
9 views•5 min read
•about 2 hours ago•CVE-2026-109619
9.2

CVE-2026-109619: Remote Code Execution in PHP Core via Stale Global State Memory Corruption (PHP2Shell)

CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.

Alon Barad
Alon Barad
10 views•6 min read
•about 2 hours ago•CVE-2026-113721
4.5

CVE-2026-113721: Unsafe Link Resolution in virtualenv File Generation

In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.

Amit Schendel
Amit Schendel
3 views•5 min read
•9 days ago•CVE-2026-87697
8.8

CVE-2026-87697: Untrusted Deserialization in .NET PresentationCore Clipboard Handling

A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.

Alon Barad
Alon Barad
31 views•5 min read
•10 days ago•CVE-2026-70007
8.8

CVE-2026-70007: Out-of-Bounds Write Vulnerability in .NET Framework and WPF Subsystem

An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.

Amit Schendel
Amit Schendel
19 views•6 min read