{"description":"Trending threats, MITRE ATT\u0026CK coverage, and detection metadata. Fed continuously.","favicon":"https://feed.craftedsignal.io/favicon-32x32.png","feed_url":"https://feed.craftedsignal.io/vendors/thephpleague/feed.json","home_page_url":"https://feed.craftedsignal.io/","icon":"https://feed.craftedsignal.io/apple-touch-icon.png","items":[{"_cs_actors":[],"_cs_cpes":[],"_cs_cves":[],"_cs_exploited":false,"_cs_has_poc":false,"_cs_poc_references":[],"_cs_products":["commonmark (\u003e= 2.7.0, \u003c 2.9.1)","commonmark (\u003e= 0.6.0, \u003c 2.9.1)"],"_cs_severities":["high"],"_cs_tags":["xss","web-vulnerability","php","supply-chain","denial-of-service","algorithmic-complexity"],"_cs_type":"advisory","_cs_vendors":["thephpleague"],"content_html":"\u003cp\u003eThe \u003ccode\u003eAttributesExtension\u003c/code\u003e for the \u003ccode\u003eleague/commonmark\u003c/code\u003e library fails to correctly sanitize attributes when a U+000C form feed character (\u003ccode\u003e\\x0C\u003c/code\u003e) is prepended to the attribute name. The library's \u003ccode\u003eAttributesHelper\u003c/code\u003e uses PHP's \u003ccode\u003etrim()\u003c/code\u003e function to clean input, but since \u003ccode\u003e\\x0C\u003c/code\u003e is excluded from the default trim character list, the character is preserved. This results in the validator failing to identify restricted attributes (such as \u003ccode\u003eonclick\u003c/code\u003e or \u003ccode\u003eonerror\u003c/code\u003e) or unsafe \u003ccode\u003ejavascript:\u003c/code\u003e URIs. Because the subsequent HTML renderer does not escape attribute names, browsers interpret the malformed tag as a valid HTML element containing the malicious handler or URI. This vulnerability affects \u003ccode\u003eleague/commonmark\u003c/code\u003e versions 2.7.0 through 2.9.0 and persists even when developers enable recommended security configurations, such as disabling \u003ccode\u003eallow_unsafe_links\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"attack-chain\"\u003eAttack Chain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eAttacker crafts a Markdown payload containing a malicious attribute or URI, prepending a U+000C character (e.g., \u003ccode\u003e{\\x0Conclick=\u0026quot;alert(1)\u0026quot;}\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eleague/commonmark\u003c/code\u003e parser encounters the attribute string during Markdown conversion.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eAttributesHelper\u003c/code\u003e matches the attribute string, including the leading \u003ccode\u003e\\x0C\u003c/code\u003e, via regex.\u003c/li\u003e\n\u003cli\u003eThe code calls PHP \u003ccode\u003etrim()\u003c/code\u003e on the attribute name, which fails to strip the \u003ccode\u003e\\x0C\u003c/code\u003e character.\u003c/li\u003e\n\u003cli\u003eThe library's \u003ccode\u003efilterAttributes()\u003c/code\u003e function compares the sanitized attribute name against an allow-list; the presence of the hidden \u003ccode\u003e\\x0C\u003c/code\u003e causes string comparisons to fail, allowing the malicious attribute to pass.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eHtmlElement\u003c/code\u003e class serializes the attribute into the final HTML output without additional validation or escaping.\u003c/li\u003e\n\u003cli\u003eThe target's browser parses the emitted HTML, treating the \u003ccode\u003e\\x0C\u003c/code\u003e as whitespace and executing the attacker's JavaScript payload.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"impact\"\u003eImpact\u003c/h2\u003e\n\u003cp\u003eSuccessful exploitation results in stored Cross-Site Scripting (XSS) in any application rendering untrusted Markdown using the \u003ccode\u003eAttributesExtension\u003c/code\u003e. Because payloads like \u003ccode\u003eonerror\u003c/code\u003e can be attached to image tags, the script executes automatically upon page load without requiring user interaction. This leads to session hijacking, unauthorized actions on behalf of the user, and potential account takeover.\u003c/p\u003e\n\u003ch2 id=\"recommendation\"\u003eRecommendation\u003c/h2\u003e\n\u003cp\u003ePrioritize patching and configuration changes to mitigate the risk of XSS exploitation.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUpgrade \u003ccode\u003eleague/commonmark\u003c/code\u003e to version 2.9.1 or later immediately.\u003c/li\u003e\n\u003cli\u003eAs a short-term workaround, define an explicit \u003ccode\u003eallow\u003c/code\u003e list for attributes (e.g., \u003ccode\u003e['id', 'class', 'align']\u003c/code\u003e) in the \u003ccode\u003eAttributesExtension\u003c/code\u003e configuration; this forces the library to reject attributes that do not match the allow-list regardless of prefix characters.\u003c/li\u003e\n\u003cli\u003eAudit applications using \u003ccode\u003eleague/commonmark\u003c/code\u003e to determine if the \u003ccode\u003eAttributesExtension\u003c/code\u003e is enabled and if inputs are retrieved from untrusted sources.\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-09-02T00:00:54Z","date_published":"2026-09-02T00:00:45Z","id":"https://feed.craftedsignal.io/briefs/2026-09-league-commonmark-xss/","summary":"An XSS vulnerability in league/commonmark allows attackers to execute arbitrary JavaScript by prepending a U+000C form feed character to malicious attribute names, bypassing security filters in the AttributesExtension.","title":"Stored XSS via Attribute Filter Bypass in league/commonmark","url":"https://feed.craftedsignal.io/briefs/2026-09-league-commonmark-xss/"}],"language":"en","title":"CraftedSignal Threat Feed - Thephpleague","version":"https://jsonfeed.org/version/1.1"}