Executive brief
The PHP League CommonMark library is a popular Markdown parser used to convert user-submitted content into safe HTML for display on websites. A vulnerability in its AttributesExtension allows attackers to inject malicious JavaScript by prefixing attribute names with an invisible control character, bypassing security filters designed to block dangerous event handlers like onclick and onerror. Exploits only execute if the parsed content is displayed in a browser, making it a stored or reflected XSS risk depending on the application's use of the library.
Technical details
The AttributesExtension filters harmful event-handler attributes (on* prefixes) and unsafe URI schemes (javascript:) using string comparisons in the filterAttributes() method. The vulnerability stems from three compounding issues: (1) PHP's trim() function does not remove the U+000C form feed byte, despite it being matched by the initial PCRE regex, leaving it inside attribute names; (2) the filter's case-insensitive string comparisons miss the malformed name because "\x0Conclick" ≠ "onclick"; and (3) the HTML renderer never escapes attribute names. When the HTML5 tokenizer parses the output, it treats U+000C as whitespace, collapsing the prefix and revealing the true attribute name. Exploitation requires untrusted Markdown input processed with AttributesExtension enabled; no prior authentication or user interaction beyond viewing the rendered HTML is required. Fixed in version 2.9.1 via attribute name normalization and stricter filtering.
Affected products
- PHP League CommonMark >= 2.7.0, < 2.9.1
Timeline
- 2026-09-07: disclosed: CVE-2026-86431 published
- 2025-05-05: patched: Fix committed (version 2.9.1)