Sep 2, 2026·6 min read·26 visits
The AttributesExtension in league/commonmark before 2.10.0 parses consecutive or adjacent HTML attributes in quadratic O(N^2) time, enabling remote denial of service via CPU exhaustion.
An algorithmic complexity vulnerability (CWE-407) in the AttributesExtension of league/commonmark allows unauthenticated remote attackers to cause CPU exhaustion and Denial of Service (DoS) via crafted Markdown payloads containing adjacent or consecutive attributes.
The popular PHP Markdown rendering engine league/commonmark includes an optional configuration module named AttributesExtension. This extension processes special inline syntax to dynamically assign class names, IDs, and miscellaneous attributes directly to HTML elements generated from Markdown. The attack surface is exposed in any deployment where user-supplied Markdown is parsed with this extension enabled.\n\nUnder the hood, the processing pipeline evaluates consecutive attribute definitions to map them to target DOM elements. In versions of league/commonmark preceding 2.10.0, the parsing logic suffers from an algorithmic complexity vulnerability classified under CWE-407 (Inefficient Algorithmic Complexity) and CWE-400 (Uncontrolled Resource Consumption). This flaw leads to severe resource exhaustion.\n\nAn unauthenticated remote attacker can exploit this behavior by submitting a payload containing a high density of structured, adjacent inline attributes or consecutive block attribute lines. The parser attempts to resolve these recursively, causing CPU consumption to scale quadratically relative to the input length, eventually hanging the PHP worker thread and exhausting system capacity.
The core issue resides in the structural handling of attribute merging and filtering within AttributesListener.php and AttributesBlockContinueParser.php. When processing contiguous attribute structures, the parser must merge incoming values into an active accumulation array. The previous implementation executed this operation inside a loop executing once for each parsed attribute node.\n\nAt each step of the iteration, the parser invoked AttributesHelper::mergeAttributes() and subsequently AttributesHelper::filterAttributes(). The filtering routine processes the entire current collection of accumulated attributes against regular expression policies to filter out forbidden schemas or unsafe URLs. Because the filter operation scales with the total size of the accumulated dictionary, this design results in quadratic O(N^2) execution complexity.\n\nphp\n// Vulnerable iterative merge and filter loop\n$attributes = $node->getAttributes();\n$merged = AttributesHelper::mergeAttributes($pending[$id]['attributes'], $attributes);\n$merged = AttributesHelper::filterAttributes($merged, $this->allowList, $this->allowUnsafeLinks);\n$pending[$id]['attributes'] = $merged;\n\n\nAs shown above, evaluating N nodes sequentially triggers N total filtration calls on arrays of increasing size, meaning the computational overhead grows exponentially with input density. Similarly, the class AttributesBlockContinueParser::tryContinue() performed iterative, sequential merging on block-level attribute configurations. When parsing a vertical sequence of attribute blocks, each new line triggered a full merge of the previously resolved attribute array, compounding the performance degradation. This vulnerability extends and completes the earlier patch for GHSA-jjv6-8j6v-6j52, which had only addressed class-attribute merge patterns.
The resolution implemented in version 2.10.0 shifts the parsing flow from continuous inline filtering to a 'Structured Accumulation and Deferred Assembly' pattern. Rather than applying regex validation and merging at each iteration step, the updated parser tracks modifications lazily, performing the intensive filter and consolidation operations once the final structure is known.\n\nThe updated AttributesListener structure uses a dedicated accumulator to map incoming data points without performing immediate merges:\n\nphp\n/**\n * @psalm-type PendingAttributes = array{\n * node: Node,\n * front: array<string, mixed>,\n * back: array<string, mixed>,\n * classFront: list<string>,\n * classBack: list<string>,\n * hasClass: bool,\n * unfiltered: array<string, mixed>\n * }\n */\n\n\nThis design segregates attributes based on append direction and isolates the specific keys modified during the current step, avoiding redundant iterations over unaffected keys.\n\nThe revised logic only processes modified keys through the validation engine, keeping the filtering operation bound to O(1) relative to the accumulator size during individual steps. The code achieves this by running filtering only against newly added elements:\n\nphp\n// Patched iteration step isolating changed keys\n$kept = AttributesHelper::filterAttributes($touched, $this->allowList, $this->allowUnsafeLinks);\n\n\nThis ensures that unmodified elements, which have already passed filtering in prior steps, are not continuously re-evaluated. When document parsing is complete, the listener executes a single, unified consolidation call via the assemble() method. The assembly routine merges the structural front, back, and class components in a single O(N) pass, entirely eliminating the O(N^2) algorithmic bottleneck.
To exploit this vulnerability, an attacker must identify an input vector that parses user-provided Markdown through league/commonmark with the AttributesExtension enabled. Since the extension is commonly deployed to support rich-text features in CMS systems, forums, and documentation platforms, this vulnerability presents a highly accessible vector. No authentication is typically required to reach the Markdown rendering engine.\n\nThe first attack vector targets adjacent inline attributes. By sending a payload with thousands of unique attribute identifiers attached to a single element, the parser is forced to perform quadratic validation cycles:\n\nmarkdown\n{a0=\"v\"}{a1=\"v\"}{a2=\"v\"}{a3=\"v\"}...{a10000=\"v\"}\n\n\nThe high concentration of distinct attributes causes severe performance degradation, quickly hitting the maximum PHP execution limit or locking the CPU core.\n\nThe second attack vector utilizes consecutive block attribute lines to exhaust resources within the block continuation parser. The payload uses consecutive lines to define block-level configurations:\n\nmarkdown\n{a0=v}\n{a1=v}\n{a2=v}\n...\n{a10000=v}\n\n\nWhen parsed, the line-by-line continue parser repeatedly invokes the dictionary merge routine, causing CPU core starvation on the application host. The third attack vector mixes attribute blocks with link references. By interspersing reference declarations with separate attributes targeting a single trailing paragraph, the event listener is forced to resolve each element sequentially, triggering the recursive merging code path. This complex structure bypasses trivial linear scanning and demonstrates the general vulnerability of the continuous-merge architecture.
Successful exploitation of GHSA-8RR7-CVQ3-GMFH allows an unauthenticated remote attacker to cause an immediate Denial of Service (DoS) of the targeted web application. Because PHP typically operates on a synchronous, thread-per-request model (such as PHP-FPM), locking up multiple worker processes with quadratic computations quickly starves the execution pool. This prevents legitimate traffic from being processed.\n\nWhile the vulnerability does not directly expose sensitive data or facilitate remote code execution, its impact on application availability is severe. In shared hosting or containerized environments, CPU exhaustion in one application container can easily degrade performance across the entire host node. This increases the potential blast radius of the attack.\n\nFrom a threat intelligence standpoint, the vulnerability has an exploit maturity classification of 'poc'. Public proof-of-concept payloads exist, but active in-the-wild exploitation remains unconfirmed. The vulnerability is not currently listed on the CISA Known Exploited Vulnerabilities (KEV) catalog, and no corresponding ransomware campaigns have been reported.
The primary and most effective remediation path is upgrading the league/commonmark package to version 2.10.0 or higher. This version integrates the structural performance optimizations that replace the continuous-merge paradigm with deferred linear assembly. Upgrading can be performed seamlessly via Composer by updating dependencies.\n\nWhen immediate patching is not possible due to legacy environment constraints, developers can mitigate the threat by temporarily disabling the AttributesExtension in the commonmark environment configuration. If attributes are not actively required by the business logic, removing this extension eliminates the attack surface completely.\n\nAdditionally, web application firewalls (WAFs) should be configured to detect and block incoming payloads with excessive attribute patterns. Implementing limits on the total length of user-supplied Markdown strings (e.g., restricting input fields to 50KB) serves as a defense-in-depth measure. This reduces the maximum size of any potential quadratic evaluation.\n\nFinally, establishing tight request timeouts and execution resource limits within PHP configurations (such as max_execution_time in php.ini and worker pool limits in php-fpm.conf) ensures that running threads are terminated before they can completely exhaust server resources. This limits the severity of any ongoing DoS attempts.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
league/commonmark thephpleague | < 2.10.0 | 2.10.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-407 (Inefficient Algorithmic Complexity) |
| Attack Vector | Network / Unauthenticated API and HTTP endpoints |
| CVSS Score | 7.5 (High) |
| Impact | Denial of Service (CPU Exhaustion) |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The product uses an algorithm with an inefficient loop or recursion that allows attackers to trigger a Denial of Service through resource exhaustion.
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.
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.
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.
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.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.