Security Vulnerability Report
中文
CVE-2026-33347 CVSS 6.1 MEDIUM

CVE-2026-33347

Published: 2026-03-24 20:16:29
Last Modified: 2026-04-08 19:01:51

Description

league/commonmark is a PHP Markdown parser. From version 2.3.0 to before version 2.8.2, the DomainFilteringAdapter in the Embed extension is vulnerable to an allowlist bypass due to a missing hostname boundary assertion in the domain-matching regex. An attacker-controlled domain like youtube.com.evil passes the allowlist check when youtube.com is an allowed domain. This issue has been patched in version 2.8.2.

CVSS Details

CVSS Score
6.1
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

Configurations (Affected Products)

cpe:2.3:a:thephpleague:commonmark:*:*:*:*:*:*:*:* - VULNERABLE
league/commonmark >= 2.3.0, < 2.8.2

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
<?php // PoC for CVE-2026-33347: DomainFilteringAdapter Bypass $allowed_domains = ['youtube.com', 'vimeo.com']; // Simulating the vulnerable regex logic (missing boundary assertions) $vulnerable_pattern = '/%s/'; $malicious_domain = 'youtube.com.evil.com'; foreach ($allowed_domains as $domain) { // Construct the regex as the vulnerable library did $pattern = sprintf($vulnerable_pattern, preg_quote($domain, '/')); if (preg_match($pattern, $malicious_domain)) { echo "[+] Bypass Successful! Malicious domain '$malicious_domain' matched allowed domain '$domain'.\n"; } else { echo "[-] Blocked.\n"; } } // Fix: Use boundary assertions like '/^' . preg_quote($domain) . '$/' ?>

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-33347", "sourceIdentifier": "[email protected]", "published": "2026-03-24T20:16:29.240", "lastModified": "2026-04-08T19:01:50.727", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "league/commonmark is a PHP Markdown parser. From version 2.3.0 to before version 2.8.2, the DomainFilteringAdapter in the Embed extension is vulnerable to an allowlist bypass due to a missing hostname boundary assertion in the domain-matching regex. An attacker-controlled domain like youtube.com.evil passes the allowlist check when youtube.com is an allowed domain. This issue has been patched in version 2.8.2."}, {"lang": "es", "value": "league/commonmark es un analizador de Markdown de PHP. Desde la versión 2.3.0 hasta antes de la versión 2.8.2, el DomainFilteringAdapter en la extensión Embed es vulnerable a una omisión de la lista de permitidos debido a una aserción de límite de nombre de host faltante en la expresión regular de coincidencia de dominio. Un dominio controlado por un atacante como youtube.com.evil pasa la verificación de la lista de permitidos cuando youtube.com es un dominio permitido. Este problema ha sido parcheado en la versión 2.8.2."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 6.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "PRESENT", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "NONE", "vulnIntegrityImpact": "LOW", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "LOW", "subIntegrityImpact": "LOW", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", "baseScore": 6.1, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "CHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 2.7}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-79"}, {"lang": "en", "value": "CWE-185"}, {"lang": "en", "value": "CWE-918"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:thephpleague:commonmark:*:*:*:*:*:*:*:*", "versionStartIncluding": "2.3.0", "versionEndExcluding": "2.8.2", "matchCriteriaId": "3AA5B677-3465-425F-BE92-CF6AD560CABF"}]}]}], "references": [{"url": "https://github.com/thephpleague/commonmark/commit/59fb075d2101740c337c7216e3f32b36c204218b", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/thephpleague/commonmark/releases/tag/2.8.2", "source": "[email protected]", "tags": ["Product", "Release Notes"]}, {"url": "https://github.com/thephpleague/commonmark/security/advisories/GHSA-hh8v-hgvp-g3f5", "source": "[email protected]", "tags": ["Mitigation", "Vendor Advisory"]}]}}