CVE-2026-33035 — wwbn/avideo
Fix: WWBN/AVideo@cca6196CVE-2026-33035 is a Cross-site Scripting (XSS) vulnerability in wwbn/avideo. No vendor fix is recorded yet; mitigation options are listed below.
Unauthenticated Reflected XSS via innerHTML in AVideo
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-33035.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
Real-World Exposure
wwbn/avideoReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.
Description
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)>
<img width="1918" height="1035" alt="image" src="https://github.com/user-attachments/assets/20077ce2-5b49-4bd3-a7df-ab48be786cc1" />
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 Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐘Packagist | wwbn/avideo | all versions | No fix |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for wwbn/avideo, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Remediation status
No patched version of wwbn/avideo has shipped for CVE-2026-33035 yet. Where your build allows, override or pin the dependency away from the vulnerable range, and apply any maintainer-recommended mitigation.
Mitigate without a patch
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-33035 can be triaged on real exposure rather than presence alone.
Tailored to CVE-2026-33035. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is CVE-2026-33035 in your dependencies?
O3 Security finds CVE-2026-33035 across Packagist dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.