Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐘
🐘 Packagist
Not in CISA KEV
MEDIUM severity

CVE-2026-34364 — wwbn/avideo

MEDIUMFix: WWBN/AVideo@6e8a673

CVE-2026-34364 is a medium-severity (CVSS 5.3) CWE-863 vulnerability in wwbn/avideo. No vendor fix is recorded yet; mitigation options are listed below.

AVideo has User Group-Based Category Access Control Bypass via Missing and Broken Group Filtering in categories.json.php

Also known asGHSA-73gr-r64q-7jh4
Published
Mar 27, 2026
Updated
Aug 12, 2026
Affected
1 pkg
Patched
See advisory
Exploits
None indexed
Exploitation data as of Sep 23, 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-34364.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs25th percentile — riskier than 25% of all scored CVEsHighest risk

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.

How urgent is this, really

CVE-2026-34364 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 378,567 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

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 categories.json.php endpoint, which serves the category listing API, fails to enforce user group-based access controls on categories. In the default request path (no ?user= parameter), user group filtering is entirely skipped, exposing all non-private categories including those restricted to specific user groups. When the ?user= parameter is supplied, a type confusion bug causes the filter to use the admin user's (user_id=1) group memberships instead of the current user's, rendering the filter ineffective.

Details

The vulnerability has two related failures in objects/categories.json.php and objects/category.php:

1. Default request — group filtering completely skipped

In categories.json.php:17-24, when $_GET['user'] is not set, $sameUserGroupAsMe defaults to false:

// categories.json.php:17-24
$onlyWithVideos = false;
$sameUserGroupAsMe = false;
if(!empty($_GET['user'])){
    $onlyWithVideos = true;
    $sameUserGroupAsMe = true;
}
$categories = Category::getAllCategories(true, $onlyWithVideos, false, $sameUserGroupAsMe);

In category.php:438-452, the user group filter is gated on $sameUserGroupAsMe being truthy:

// category.php:438-452
if ($sameUserGroupAsMe) {
    $users_groups = UserGroups::getUserGroups($sameUserGroupAsMe);
    $users_groups_id = array(0);
    foreach ($users_groups as $value) {
        $users_groups_id[] = $value['id'];
    }
    $sql .= " AND ("
        . "(SELECT count(*) FROM categories_has_users_groups chug WHERE c.id = chug.categories_id) = 0 OR "
        . "(SELECT count(*) FROM categories_has_users_groups chug2 WHERE c.id = chug2.categories_id AND users_groups_id IN (" . implode(',', $users_groups_id) . ")) >= 1 "
        . ")";
}

Since $sameUserGroupAsMe = false, the entire block is skipped. All non-private categories are returned regardless of their user group restrictions set via the categories_has_users_groups table.

2. With ?user= parameter — boolean-to-integer type confusion

When $_GET['user'] is non-empty, $sameUserGroupAsMe is set to boolean true (line 21). This value is passed to UserGroups::getUserGroups($sameUserGroupAsMe) at category.php:440.

In userGroups.php:349-379, the parameter is used as $users_id:

// userGroups.php:349,371,379
public static function getUserGroups($users_id){
    // ...
    $sql = "SELECT uug.*, ug.* FROM users_groups ug"
            . " LEFT JOIN users_has_users_groups uug ON users_groups_id = ug.id WHERE users_id = ? ";
    // ...
    $res = sqlDAL::readSql($sql, "i", [$users_id]);

PHP casts boolean true to integer 1 for the prepared statement bind, resulting in WHERE users_id = 1 — fetching the admin user's group memberships. The filter then allows categories visible to admin groups, effectively granting any unauthenticated user the admin's category visibility.

3. getTotalCategories also unfiltered

getTotalCategories() at category.php:978 does not accept a $sameUserGroupAsMe parameter at all, so the total count always reflects the unfiltered category set.

The endpoint requires no authentication — it uses allowOrigin() (a CORS header helper) and is publicly routable via the .htaccess rewrite rule: RewriteRule ^categories.json$ objects/categories.json.php.

PoC

# 1. Fetch all categories without authentication — no group filtering applied
curl -s 'https://target/categories.json' | jq '.rows[] | {id, name, private, users_groups_ids_array}'

# Returns ALL non-private categories including those restricted to specific user groups.
# The users_groups_ids_array field reveals which groups each category is restricted to.
# Categories with non-empty users_groups_ids_array should be hidden from users not in those groups.

# 2. Attempt the "filtered" path — still broken due to boolean->int cast
curl -s 'https://target/categories.json?user=1' | jq '.rows[] | {id, name, private, users_groups_ids_array}'

# This applies group filtering but uses admin's groups (users_id=1) instead of the
# current user's groups, so group-restricted categories visible to admin are exposed.

Impact

Any unauthenticated user can:

  • Enumerate all non-private categories regardless of user group restrictions, bypassing the intended access control model where categories are restricted to specific user groups via the CustomizeUser plugin's categories_has_users_groups table.
  • Discover the user group configuration for each category via the users_groups_ids_array field in the response, revealing the internal access control structure.
  • Identify group-restricted content areas that should be hidden, which could be used to target further access control bypasses on the videos within those categories.

The severity is Medium because this is an information disclosure of category metadata (names, descriptions, icons, group assignments) rather than the actual video content within restricted categories. However, the exposure of the access control structure itself (which groups have access to which categories) is a meaningful information leak.

Recommended Fix

In objects/categories.json.php, pass the current user's ID (or 0 for unauthenticated users) instead of a boolean:

// categories.json.php — replace lines 17-24
$onlyWithVideos = false;
$sameUserGroupAsMe = false;
if(!empty($_GET['user'])){
    $onlyWithVideos = true;
}
// Always apply user group filtering using the logged-in user's ID
$currentUserId = User::getId();
if (!empty($currentUserId)) {
    $sameUserGroupAsMe = $currentUserId;
} else {
    // For unauthenticated users, pass a value that will filter to only
    // categories with no group restrictions
    $sameUserGroupAsMe = -1; // Non-existent user ID, will match no groups
}

$categories = Category::getAllCategories(true, $onlyWithVideos, false, $sameUserGroupAsMe);

Additionally, in category.php:getAllCategories(), ensure the group filter block always runs when categories have group restrictions, not only when $sameUserGroupAsMe is truthy. A more robust approach:

// category.php — replace the sameUserGroupAsMe block (lines 438-452)
// Always filter by user groups if any categories have group restrictions
$users_groups_id = array(0);
if ($sameUserGroupAsMe && $sameUserGroupAsMe > 0) {
    $users_groups = UserGroups::getUserGroups($sameUserGroupAsMe);
    foreach ($users_groups as $value) {
        $users_groups_id[] = $value['id'];
    }
}
$sql .= " AND ("
    . "(SELECT count(*) FROM categories_has_users_groups chug WHERE c.id = chug.categories_id) = 0 OR "
    . "(SELECT count(*) FROM categories_has_users_groups chug2 WHERE c.id = chug2.categories_id AND users_groups_id IN (" . implode(',', $users_groups_id) . ")) >= 1 "
    . ")";

This ensures that even when no user is logged in, categories with group restrictions are hidden (only categories with zero group restrictions are shown). The getTotalCategories() function should also be updated to accept and apply the same $sameUserGroupAsMe filter.

Affected Packages

1 total
EcosystemPackageVulnerable rangeFix
🐘Packagistwwbn/avideoall versionsNo fix

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

    No patched version of wwbn/avideo has shipped for CVE-2026-34364 yet. Where your build allows, override or pin the dependency away from the vulnerable range, and apply any maintainer-recommended mitigation.

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

  4. 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-34364 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-34364. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## Summary The `categories.json.php` endpoint, which serves the category listing API, fails to enforce user group-based access controls on categories. In the default request path (no `?user=` parameter), user group filtering is entirely skipped, exposing all non-private categories including those restricted to specific user groups. When the `?user=` parameter is supplied, a type confusion bug causes the filter to use the admin user's (user_id=1) group memberships instead of the current user's, rendering the filter ineffective. ## Details The vulnerability has two related failures in `object
O3 Security · Impact-Aware SCA

Is CVE-2026-34364 in your dependencies?

O3 Security finds CVE-2026-34364 across Packagist dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-34364: wwbn/avideo (Medium 5.3) | O3 Security