CVE-2026-34364: AVideo has User Group-Based Category Access Control Bypass via Missing and Broken Group Filtering in categories.json.php
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 (userid=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:
php // 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:
php // category.php:438-452 if ($sameUserGroupAsMe) { $usersgroups = UserGroups::getUserGroups($sameUserGroupAsMe); $usersgroupsid = array(0); foreach ($usersgroups as $value) { $usersgroupsid[] = $value['id']; } $sql .= " AND (" . "(SELECT count() FROM categorieshasusersgroups chug WHERE c.id = chug.categoriesid) = 0 OR " . "(SELECT count() FROM categorieshasusersgroups chug2 WHERE c.id = chug2.categoriesid AND usersgroupsid IN (" . implode(',', $usersgroupsid) . ")) >= 1 " . ")"; }
Since $sameUserGroupAsMe = false, the entire block is skipped. All non-private categories are returned regardless of their user group restrictions set via the categorieshasusersgroups 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 $usersid:
php // userGroups.php:349,371,379 public static function getUserGroups($usersid){ // ... $sql = "SELECT uug., ug. FROM usersgroups ug" . " LEFT JOIN usershasusersgroups uug ON usersgroupsid = ug.id WHERE usersid = ? "; // ... $res = sqlDAL::readSql($sql, "i", [$usersid]);
PHP casts boolean true to integer 1 for the prepared statement bind, resulting in WHERE usersid = 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
bash 1. Fetch all categories without authentication — no group filtering applied curl -s 'https://target/categories.json' | jq '.rows[] | {id, name, private, usersgroupsidsarray}'
Returns ALL non-private categories including those restricted to specific user groups. The usersgroupsidsarray field reveals which groups each category is restricted to. Categories with non-empty usersgroupsidsarray 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, usersgroupsidsarray}'
This applies group filtering but uses admin's groups (usersid=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 categorieshasusersgroups table. - Discover the user group configuration for each category via the usersgroupsidsarray 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:
php // 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:
php // category.php — replace the sameUserGroupAsMe block (lines 438-452) // Always filter by user groups if any categories have group restrictions $usersgroupsid = array(0); if ($sameUserGroupAsMe && $sameUserGroupAsMe > 0) { $usersgroups = UserGroups::getUserGroups($sameUserGroupAsMe); foreach ($usersgroups as $value) { $usersgroupsid[] = $value['id']; } } $sql .= " AND (" . "(SELECT count() FROM categorieshasusersgroups chug WHERE c.id = chug.categoriesid) = 0 OR " . "(SELECT count() FROM categorieshasusersgroups chug2 WHERE c.id = chug2.categoriesid AND usersgroupsid IN (" . implode(',', $usersgroupsid) . ")) >= 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.
Other sources
WWBN AVideo is an open source video platform. In versions up to and including 26.0, 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 (userid=1) group memberships instead of the current user's, rendering the filter ineffective. Commit 6e8a673eed07be5628d0b60fbfabd171f3ce74c9 contains a fix.
— MITRE
Affected Software
Remediation
Event History
Frequently Asked Questions
What is the severity of CVE-2026-34364?
CVE-2026-34364 has been assigned a high severity rating due to its potential for unauthorized access control bypass.
How do I fix CVE-2026-34364?
To fix CVE-2026-34364, upgrade to the latest version of AVideo beyond version 26.0 where the vulnerability has been patched.
What systems are affected by CVE-2026-34364?
CVE-2026-34364 affects all versions of WWBN AVideo up to and including version 26.0.
Can CVE-2026-34364 be exploited remotely?
Yes, CVE-2026-34364 can be exploited remotely due to the nature of the affected API endpoint.
What type of attack does CVE-2026-34364 enable?
CVE-2026-34364 enables an attacker to bypass user group-based access controls, potentially exposing sensitive category data.