Unauthenticated Reflected XSS via innerHTML in AVideo
Summary
AVideo contains a reflected XSS vulnerability that allows unauthenticated attackers to execute arbitrary JavaScript in a victim's browser. User input from a URL parameter flows through PHP's json_encode() into a JavaScript function that renders it via innerHTML, bypassing encoding and achieving full script execution.
Root Cause
The vulnerability is caused by two issues working together:
1. Source: Unescaped user input passed to JavaScript (videoNotFound.php)
File: view/videoNotFound.php line 49
if (!empty($_REQUEST['404ErrorMsg'])) {
echo 'avideoAlertInfo(' . json_encode($_REQUEST['404ErrorMsg']) . ');';
}
PHP's json_encode() with default flags only escapes quotes (" → \") and backslashes. It does NOT escape HTML special characters (<, >, /). The resulting string contains raw HTML tags that are passed directly to JavaScript.
2. Sink: innerHTML renders HTML tags as executable DOM (script.js)
File: view/js/script.js
function avideoAlertInfo(msg) { // line ~1891
avideoAlert("", msg, 'info'); // calls ↓
}
function avideoAlert(title, msg, type) { // line ~1270
avideoAlertHTMLText(title, msg, type); // calls ↓
}
function avideoAlertHTMLText(title, msg, type) { // line ~1451
var span = document.createElement("span");
span.innerHTML = msg; // line 1464 — XSS SINK
swal({ content: span });
}
innerHTML parses the string as HTML. Any <img>, <svg>, or other HTML tags with event handlers are instantiated as real DOM elements, triggering JavaScript execution.
Data Flow
URL parameter (?404ErrorMsg=PAYLOAD)
→ $_REQUEST['404ErrorMsg']
→ json_encode() ← does NOT escape < > /
→ avideoAlertInfo()
→ avideoAlert()
→ avideoAlertHTMLText()
→ span.innerHTML = msg ← renders HTML tags, executes JS
Proof of Concept
https://localhost/view/videoNotFound.php?404ErrorMsg=<img src=x onerror=alert(document.domain)>
The page renders:
avideoAlertInfo("<img src=x onerror=alert(document.domain)>");
Which flows to span.innerHTML = "<img src=x onerror=alert(document.domain)>". The browser creates an <img> element, src=x fails to load, onerror fires alert(document.domain).
Affected Code
| File | Line | Issue |
|---|---|---|
view/videoNotFound.php |
49 | json_encode() does not escape < > for HTML context |
view/js/script.js |
1464 | span.innerHTML = msg renders user input as HTML |
view/js/script.js |
1282 | span.innerHTML = msg in avideoAlertWithCookie() |
view/js/script.js |
1335 | span.innerHTML = __(msg,true) in avideoConfirm() |
view/js/script.js |
1358 | span.innerHTML = msg in avideoAlertOnceForceConfirm() |
The innerHTML sink exists in 4 functions. Any future code that passes user input to avideoAlertInfo(), avideoAlertWarning(), avideoAlertDanger(), or avideoAlertSuccess() will create additional XSS vectors.
Remediation
Fix 1: Escape HTML in PHP (source fix)
// view/videoNotFound.php line 49
// BEFORE (vulnerable):
echo 'avideoAlertInfo(' . json_encode($_REQUEST['404ErrorMsg']) . ');';
// AFTER (fixed):
echo 'avideoAlertInfo(' . json_encode($_REQUEST['404ErrorMsg'], JSON_HEX_TAG | JSON_HEX_AMP) . ');';
JSON_HEX_TAG converts < → \u003C and > → \u003E, preventing HTML injection.
Fix 2: Use textContent instead of innerHTML (sink fix, recommended)
// view/js/script.js - all alert functions
// BEFORE (vulnerable):
span.innerHTML = msg;
// AFTER (fixed):
span.textContent = msg;
textContent treats the string as plain text — HTML tags are displayed literally, never parsed or executed.
Fix 3: Add Content-Security-Policy header (defense in depth)
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
Impact
- Session hijacking — steal
PHPSESSIDcookie (not HttpOnly by default) - Account takeover — use stolen session to change password or email
- Phishing — inject a realistic login form inside the SweetAlert modal
- Worm propagation — inject self-spreading payloads via comments/messages
- Admin compromise — send crafted link to admin, steal session, gain full control
Affected software
Click a technology to see all vulnerabilities affecting it.
| Platform | Package | Vulnerable versions | Fixed in |
|---|---|---|---|
| Composer package | wwbn/avideo | <= 25.0 | no fix |
References
- CVSS vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N- Weakness (CWE)
CWE-79- Platform
- Composer
- Package
wwbn/avideo- Disclosed
- 17.03.2026
- Updated
- 11.10.2026 10:22
Sources and licenses
OSV / GitHub Advisory Database - GHSA-wfq5-qgqp-hvhv - 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.
- 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
- 2022: 2
- 2023: 5
- 2024: 5
- 2025: 0
- 2026: 148
-
Unauthenticated Reflected XSS via innerHTML in AVideo this entry
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.