league/commonmark AttributesExtension Denial of Service, CVE-2026-71478 (High) -DC-Sep2026-2071

Listen to this Post

The league/commonmark PHP library provides an opt-in AttributesExtension that allows users to attach HTML attributes to Markdown elements. When this extension is enabled, two distinct processing paths suffer from an algorithmic inefficiency: they re-process every attribute a node has already collected each time another attribute is applied to it. Because the attributes carry distinct names, the collected set grows by one on every step and is walked again in full — resulting in O(n²) time complexity for a run of n attributes.
Path 1: Attribute nodes resolving to a common target (affected from 1.5.0). `AttributesListener::processDocument()` merges each attribute node into the set accumulated for its target, then filters the result. Both operations traverse the entire set: `AttributesHelper::mergeAttributes()` rebuilds it with array_merge(), and `AttributesHelper::filterAttributes()` matches a regular expression against every name in it. A run of attribute nodes sharing one target re-walks a set that grows by a key per node. Two input shapes reach this path: adjacent inline attributes at the start of a block ({a0="v"}{a1="v"}…) — quoting the values keeps them separate; an unquoted value swallows the `}{` that follows it — and a chain of attribute blocks held at their default target by reference definitions ({a0=v} /

: u / {a1=v} / [bash]: u / …</code>). A 256 KB payload of adjacent inline attributes takes 20.0 seconds to convert, against 0.09 seconds once patched.
Path 2: Consecutive attribute-block lines (affected from 2.0.0). `AttributesBlockContinueParser::tryContinue()` merges each continuation line into the block's accumulated attributes, rebuilding the whole set on every line. One distinct attribute per line (<code>{a0=v} / {a1=v} / …</code>) grows the set by a key each time. A 256 KB input of such lines takes 1.9 seconds to convert while producing zero bytes of output, against 0.08 seconds once patched.
Relationship to GHSA-jjv6-8j6v-6j52. The fix released in 2.9.1 for that advisory made the `class` attribute cheap to accumulate, but left every other attribute name on the original path. Applications that upgraded to 2.9.1 or 2.9.2 remain exposed.
Overall impact. An unauthenticated attacker who can submit Markdown to an affected application can consume disproportionate CPU time with a comparatively small request, occupying PHP workers and preventing legitimate requests from completing. The impact is limited to availability: no data is disclosed, rendered output is unchanged, and no rendering restriction is bypassed.

<h2 style="color: blue;">DailyCVE Form:</h2>

Platform: PHP, Composer
Version: 1.5.0–2.9.2
Vulnerability: Denial of Service
Severity: High (CVSS 7.5)
Date: August 7, 2026

<h2 style="color: blue;">Prediction: Patch available (2.10.0)</h2>

<h2 style="color: blue;">What Undercode Say:</h2>

[bash]
Check your league/commonmark version
composer show league/commonmark
Update to patched version
composer update league/commonmark:^2.10.0
Verify the update
composer show league/commonmark | grep versions

Exploit: (Educational Purposes!)

// Path 1: Adjacent inline attributes at block start
$payload = str_repeat('{a="v"}', 8000);
// A ~32 KB payload can take over 5 seconds to convert
// Path 2: Consecutive attribute-block lines
$payload = "";
for ($i = 0; $i < 8000; $i++) {
$payload .= "{a$i=v}\n";
}
// 256 KB takes 1.9 seconds with zero output
// Vulnerable code path (simplified)
// AttributesHelper::mergeAttributes() rebuilds entire set with array_merge()
// AttributesHelper::filterAttributes() regex-matches every name

Protection from this CVE:

1. Upgrade immediately to league/commonmark 2.10.0 or later.

  1. Do not register `AttributesExtension` when converting untrusted Markdown.
  2. If the extension is required, impose a strict maximum input length before conversion. Because the cost is quadratic, the cap must be small to meaningfully bound worst-case CPU time.
  3. The `attributes/allow` allow-list added in 2.7.0 is not a mitigation — it does nothing for the second path, as continuation lines are merged during parsing before any filtering takes place.
  4. Restricting conversion to trusted users, applying strict execution-time limits, and rate-limiting requests reduce exposure but are not substitutes for upgrading.

Impact:

  • Availability: High — CPU exhaustion, PHP worker starvation, denial of service
  • Confidentiality: None — no data disclosure
  • Integrity: None — rendered output unchanged
  • Authentication: None required — unauthenticated attacker
  • User Interaction: None required
  • Attack complexity: Low — simple crafted Markdown input

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top