CVE-2025-46734 Overview
A cross-site scripting (XSS) vulnerability has been identified in the Attributes extension of the league/commonmark library, a widely-used PHP Markdown parser. This vulnerability affects versions 1.5.0 through 2.6.x and allows remote attackers to inject malicious JavaScript calls into HTML output by exploiting the curly brace syntax used for attribute injection in Markdown.
The league/commonmark library provides configuration options such as html_input: 'strip' and allow_unsafe_links: false to mitigate XSS attacks by stripping raw HTML and disallowing unsafe links. However, when the Attributes Extension is enabled, it introduces a way for users to inject arbitrary HTML attributes into elements via Markdown syntax using curly braces, effectively bypassing these protective measures.
Critical Impact
Attackers can inject arbitrary HTML attributes including event handlers (e.g., onclick, onerror) to execute malicious JavaScript in the context of victim users' browsers, potentially leading to session hijacking, credential theft, or malware distribution.
Affected Products
- league/commonmark versions 1.5.0 through 2.6.x
- PHP applications using the Attributes Extension
- Web applications parsing untrusted Markdown input with AttributesExtension enabled
Discovery Timeline
- 2025-05-05 - CVE CVE-2025-46734 published to NVD
- 2025-05-05 - Last updated in NVD database
Technical Details for CVE-2025-46734
Vulnerability Analysis
This vulnerability is classified as CWE-79 (Improper Neutralization of Input During Web Page Generation), commonly known as Cross-Site Scripting (XSS). The attack vector is network-based and requires low privileges to exploit, making it accessible to authenticated users with the ability to submit Markdown content.
The core issue lies in the Attributes Extension's design, which allows users to specify arbitrary HTML attributes using curly brace syntax in Markdown documents. While the library's core security settings (html_input: 'strip' and allow_unsafe_links: false) are intended to prevent XSS attacks, the Attributes Extension operates independently of these controls, creating a security gap.
When processing Markdown content, the extension parses curly brace notation and directly applies the specified attributes to HTML elements without adequate filtering. This allows attackers to inject event handler attributes (such as onclick, onmouseover, onerror) that execute JavaScript when triggered by user interaction.
Root Cause
The root cause stems from insufficient attribute filtering in the AttributesExtension and AttributesListener classes. The original implementation did not validate or sanitize attribute names before applying them to HTML elements, nor did it respect the existing security configuration options designed to prevent XSS attacks.
Specifically, the AttributesListener class processed user-supplied attributes without:
- Blocking event handler attributes (attributes starting with on)
- Implementing an allowlist for permitted attributes
- Respecting the allow_unsafe_links configuration for href and src attributes
Attack Vector
An attacker with the ability to submit Markdown content can craft malicious input using the curly brace syntax to inject JavaScript event handlers. When a victim views the rendered HTML output, the injected JavaScript executes in their browser context.
For example, a malicious Markdown input might include attributes like {onclick="malicious_code()"} appended to links or images. Since the Attributes Extension did not filter these attributes, the resulting HTML would include the event handler, ready to execute when triggered.
The fix implemented in version 2.7.0 addresses this vulnerability through three key changes visible in the security patch:
// Security patch in src/Extension/Attributes/AttributesExtension.php
use League\CommonMark\Extension\Attributes\Event\AttributesListener;
use League\CommonMark\Extension\Attributes\Parser\AttributesBlockStartParser;
use League\CommonMark\Extension\Attributes\Parser\AttributesInlineParser;
-use League\CommonMark\Extension\ExtensionInterface;
+use League\CommonMark\Extension\ConfigurableExtensionInterface;
+use League\Config\ConfigurationBuilderInterface;
+use Nette\Schema\Expect;
-final class AttributesExtension implements ExtensionInterface
+final class AttributesExtension implements ConfigurableExtensionInterface
{
+ public function configureSchema(ConfigurationBuilderInterface $builder): void
+ {
+ $builder->addSchema('attributes', Expect::structure([
+ 'allow' => Expect::arrayOf('string')->default([]),
+ ]));
+ }
+
public function register(EnvironmentBuilderInterface $environment): void
{
+ $allowList = $environment->getConfiguration()->get('attributes.allow');
+ $allowUnsafeLinks = $environment->getConfiguration()->get('allow_unsafe_links');
+
$environment->addBlockStartParser(new AttributesBlockStartParser());
$environment->addInlineParser(new AttributesInlineParser());
- $environment->addEventListener(DocumentParsedEvent::class, [new AttributesListener(), 'processDocument']);
+ $environment->addEventListener(DocumentParsedEvent::class, [new AttributesListener($allowList, $allowUnsafeLinks), 'processDocument']);
}
}
Source: GitHub Commit Changes
The AttributesListener was also updated to accept and enforce security configuration:
// Security patch in src/Extension/Attributes/Event/AttributesListener.php
private const DIRECTION_PREFIX = 'prefix';
private const DIRECTION_SUFFIX = 'suffix';
+ /** @var list<string> */
+ private array $allowList;
+ private bool $allowUnsafeLinks;
+
+ /**
+ * @param list<string> $allowList
+ */
+ public function __construct(array $allowList = [], bool $allowUnsafeLinks = true)
+ {
+ $this->allowList = $allowList;
+ $this->allowUnsafeLinks = $allowUnsafeLinks;
+ }
+
public function processDocument(DocumentParsedEvent $event): void
{
foreach ($event->getDocument()->iterator() as $node) {
Source: GitHub Commit Changes
Detection Methods for CVE-2025-46734
Indicators of Compromise
- Presence of event handler attributes (onclick, onerror, onload, onmouseover, etc.) in rendered HTML output from Markdown content
- Markdown content containing curly brace syntax with suspicious attribute names starting with on
- User-submitted content containing JavaScript URIs (javascript:) within attribute values
- Unexpected JavaScript execution in pages displaying user-generated Markdown content
Detection Strategies
- Review application dependencies for league/commonmark versions between 1.5.0 and 2.6.x using composer show league/commonmark
- Implement Content Security Policy (CSP) headers to detect and block inline script execution attempts
- Monitor web application firewall (WAF) logs for requests containing curly brace notation with event handler patterns
- Audit existing Markdown content in databases for potentially malicious attribute injections
Monitoring Recommendations
- Enable SentinelOne Singularity Platform to detect anomalous JavaScript execution patterns in web application contexts
- Configure browser-based XSS auditors and CSP violation reporting to capture exploitation attempts
- Implement logging for Markdown rendering operations to track input patterns that may indicate attack attempts
- Deploy runtime application self-protection (RASP) solutions to detect XSS payloads at the application layer
How to Mitigate CVE-2025-46734
Immediate Actions Required
- Upgrade league/commonmark to version 2.7.0 or later immediately
- Audit all Markdown rendering configurations to identify instances where AttributesExtension is enabled
- Review stored user-generated Markdown content for potential malicious attribute injections
- Implement Content Security Policy headers with strict inline script restrictions as a defense-in-depth measure
Patch Information
The vulnerability has been patched in league/commonmark version 2.7.0. The fix implements three critical security improvements:
- All attributes starting with on are now considered unsafe and blocked by default
- Support for an explicit allowlist of permitted HTML attributes via the attributes.allow configuration option
- Manually-added href and src attributes now respect the existing allow_unsafe_links configuration option
Update via Composer:
composer require league/commonmark:^2.7.0
For detailed patch information, refer to the GitHub Security Advisory GHSA-3527-qv2q-pfvx.
Workarounds
- Disable the AttributesExtension entirely for untrusted users if upgrading is not immediately feasible
- Filter rendered HTML output through a sanitization library like HTMLPurifier before displaying to users
- Implement a custom attribute filter to strip event handler attributes before the Markdown is processed
- Restrict Markdown input to trusted, authenticated users only until the patch can be applied
# Configuration example - Disable AttributesExtension in PHP
# Remove or comment out the extension registration:
# $environment->addExtension(new AttributesExtension());
# If using with attributes in version 2.7.0+, configure allowlist:
# 'attributes' => [
# 'allow' => ['class', 'id', 'href', 'src', 'alt', 'title'],
# ],
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


