CVE-2026-33684: Wwbn/avideo AVideo's Privilege Escalation Vulnerability

MODERATE
Advisory Identifier: GHSA-8j8m-p79x-g4jm
CVSS 5.3
CWE-862
Published
Advisory Summary

CVE-2026-33684 is a MODERATE (CVSS 5.3) avideo's privilege escalation vulnerability (CWE-862: Missing Authorization) affecting Wwbn/avideo libraries in the Packagist ecosystem. The issue involves avideo's privilege escalation via unguarded permission parameters in signup api allows self-granting upload/stream/meet permissions. Remediation is available by upgrading affected packages to version 29.0.

CVE-2026-33684 at a Glance

CVE Identifier CVE-2026-33684
GHSA Identifier GHSA-8j8m-p79x-g4jm
Severity MODERATE
CVSS v3.1 Base Score 5.3
CWE Classification CWE-862: Missing Authorization
Affected Product Wwbn/avideo
Package Ecosystem Packagist
Published Date
Last Updated

Security Impact

CVSS: 5.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity Low (I:L)
Availability None (A:N)

How to Fix CVE-2026-33684

To remediate this vulnerability, upgrade all affected Wwbn/avideo dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

wwbn/avideo fixed: 29.0
Upgrade wwbn/avideo to 29.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for wwbn/avideo

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-33684, inspect your project dependencies for Wwbn/avideo:

inspect dependencies for wwbn/avideo

Analyze the terminal output to locate any version of Wwbn/avideo in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 29.0), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-862: Missing Authorization, where the product does not perform an authorization check when an actor attempts to access a resource or perform an action. In Wwbn/avideo, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary The `set_api_signUp` method in the API plugin accepts `emailVerified`, `canUpload`, `canStream`, and `canCreateMeet` parameters from user-supplied input and applies them to newly created accounts without verifying that the request was authenticated with a valid APISecret. Any anonymous user who can solve a CAPTCHA can self-grant elevated permissions during account registration. ## Details The authentication check in `set_api_signUp` (`plugin/API/API.php:4222`) allows either a valid APISecret (admin-level credential) or a solved CAPTCHA (anonymous access): ```php // plugin/API/API.php:4222-4232 if ($obj->APISecret !== @$_REQUEST['APISecret']) { if(empty($_REQUEST['captcha'])){ return new ApiObject("Captcha is required"); } require_once $global['systemRootPath'] . 'objects/captcha.php'; $valid = Captcha::validation($_REQUEST['captcha']); if(!$valid){ return new ApiObject("Captcha is wrong, reload it and try again"); } } ``` After this check, both code paths (APISecret and CAPTCHA) reach the privilege parameter handling unconditionally: ```php // plugin/API/API.php:4238-4249 if (isset($_REQUEST['emailVerified'])) { $global['emailVerified'] = intval($_REQUEST['emailVerified']); } if (isset($_REQUEST['canCreateMeet'])) { $global['canCreateMeet'] = intval($_REQUEST['canCreateMeet']); } if (isset($_REQUEST['canStream'])) { $global['canStream'] = intval($_REQUEST['canStream']); } if (isset($_REQUEST['canUpload'])) { $global['canUpload'] = intval($_REQUEST['canUpload']); } ``` These `$global` values are then consumed by `User::save()` (`objects/user.php:829-840`), which overrides the user object's permission fields: ```php // objects/user.php:829-840 if (isset($global['emailVerified'])) { $this->emailVerified = $global['emailVerified']; } if (isset($global['canCreateMeet'])) { $this->canCreateMeet = $global['canCreateMeet']; } if (isset($global['canStream'])) { $this->canStream = $global['canStream']; } if (isset($global['canUpload'])) { $this->canUpload = $global['canUpload']; } ``` Note that even though `userCreate.json.php:90` sets `canUpload` from the site's default configuration, `User::save()` subsequently overrides it with the attacker-controlled `$global` value. The codebase already uses `self::isAPISecretValid()` to guard admin-only operations in other API methods (e.g., lines 294, 991, 1664, 2150), but this check is missing for the privilege parameters in `set_api_signUp`. ## PoC ```bash # Step 1: Get a CAPTCHA token # (Navigate to the signup page in a browser, solve the CAPTCHA, capture the token) # Step 2: Register with elevated privileges curl -X POST 'https://target/plugin/API/set.json.php' \ -d 'APIName=signUp' \ -d 'user=attacker' \ -d 'pass=Password123!' \ -d 'email=attacker@example.com' \ -d 'name=Attacker' \ -d 'captcha=VALID_CAPTCHA_TOKEN' \ -d 'emailVerified=1' \ -d 'canUpload=1' \ -d 'canStream=1' \ -d 'canCreateMeet=1' # Expected: Account created with default (restricted) permissions # Actual: Account created with upload, stream, and meet permissions enabled, # plus email marked as verified # Step 3: Verify elevated permissions by logging in and checking profile curl -X POST 'https://target/plugin/API/set.json.php' \ -d 'APIName=signIn' \ -d 'user=attacker' \ -d 'pass=Password123!' # Response will show canUpload=1, canStream=1, canCreateMeet=1, emailVerified=1 ``` ## Impact - **Email verification bypass:** Attackers can mark their accounts as email-verified without owning the email address, bypassing any email-gated functionality - **Unauthorized upload access:** Self-granted upload permissions allow uploading potentially malicious video content to the platform - **Unauthorized streaming access:** Self-granted streaming permissions allow unauthorized live streaming - **Unauthorized meeting creation:** Self-granted meet permissions allow creating meetings on the platform - **Policy bypass:** Platform administrators who intentionally restrict these permissions for new users (e.g., requiring manual approval before granting upload rights) have their access controls circumvented ## Recommended Fix Wrap the privilege parameter handling in an `isAPISecretValid()` check so that only admin-authenticated requests can set these values: ```php // plugin/API/API.php — replace lines 4238-4249 with: if (self::isAPISecretValid()) { if (isset($_REQUEST['emailVerified'])) { $global['emailVerified'] = intval($_REQUEST['emailVerified']); } if (isset($_REQUEST['canCreateMeet'])) { $global['canCreateMeet'] = intval($_REQUEST['canCreateMeet']); } if (isset($_REQUEST['canStream'])) { $global['canStream'] = intval($_REQUEST['canStream']); } if (isset($_REQUEST['canUpload'])) { $global['canUpload'] = intval($_REQUEST['canUpload']); } } ```

CVE-2026-33684 Affected Wwbn/avideo Versions

1 component(s)
Fixed Versions:
29.0
Product / Package Ecosystem Affected Versions Fixed Version
wwbn/avideo
Packagist
< 29.0
29.0

References

Frequently Asked Questions

What is CVE-2026-33684?
CVE-2026-33684 is a security vulnerability in Wwbn/avideo involving AVideo's Privilege Escalation via Unguarded Permission Parameters in signUp API Allows Self-Granting Upload/Stream/Meet Permissions under CWE-862: Missing Authorization.
Which Wwbn/avideo versions are affected?
Affected versions include releases prior to 29.0 across affected packages: wwbn/avideo.
What version fixes CVE-2026-33684?
Upgrading to 29.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is wwbn/avideo affected?
Yes, wwbn/avideo is affected in releases prior to 29.0. Upgrade your dependency to 29.0 or later.
What is the CVSS score of CVE-2026-33684?
CVE-2026-33684 has a CVSS v3.1 base score of 5.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N.
What CWE is associated with CVE-2026-33684?
CVE-2026-33684 is classified under CWE-862: Missing Authorization (The product does not perform an authorization check when an actor attempts to access a resource or perform an action.).
How can I check Packagist dependencies for CVE-2026-33684?
Run the dependency tree command: 'inspect dependencies for wwbn/avideo'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-8j8m-p79x-g4jm",
  "modified" : "2026-06-22T17:25:03Z",
  "published" : "2026-06-22T17:25:03Z",
  "aliases" : [ "CVE-2026-33684" ],
  "summary" : "AVideo's Privilege Escalation via Unguarded Permission Parameters in signUp API Allows Self-Granting Upload/Stream/Meet Permissions",
  "details" : "## Summary\n\nThe `set_api_signUp` method in the API plugin accepts `emailVerified`, `canUpload`, `canStream`, and `canCreateMeet` parameters from user-supplied input and applies them to newly created accounts without verifying that the request was authenticated with a valid APISecret. Any anonymous user who can solve a CAPTCHA can self-grant elevated permissions during account registration.\n\n## Details\n\nThe authentication check in `set_api_signUp` (`plugin/API/API.php:4222`) allows either a valid APISecret (admin-level credential) or a solved CAPTCHA (anonymous access):\n\n```php\n// plugin/API/API.php:4222-4232\nif ($obj->APISecret !== @$_REQUEST['APISecret']) {\n    if(empty($_REQUEST['captcha'])){\n        return new ApiObject(\"Captcha is required\");\n    }\n    require_once $global['systemRootPath'] . 'objects/captcha.php';\n    $valid = Captcha::validation($_REQUEST['captcha']);\n    if(!$valid){\n        return new ApiObject(\"Captcha is wrong, reload it and try again\");\n    }\n}\n```\n\nAfter this check, both code paths (APISecret and CAPTCHA) reach the privilege parameter handling unconditionally:\n\n```php\n// plugin/API/API.php:4238-4249\nif (isset($_REQUEST['emailVerified'])) {\n    $global['emailVerified'] = intval($_REQUEST['emailVerified']);\n}\nif (isset($_REQUEST['canCreateMeet'])) {\n    $global['canCreateMeet'] = intval($_REQUEST['canCreateMeet']);\n}\nif (isset($_REQUEST['canStream'])) {\n    $global['canStream'] = intval($_REQUEST['canStream']);\n}\nif (isset($_REQUEST['canUpload'])) {\n    $global['canUpload'] = intval($_REQUEST['canUpload']);\n}\n```\n\nThese `$global` values are then consumed by `User::save()` (`objects/user.php:829-840`), which overrides the user object's permission fields:\n\n```php\n// objects/user.php:829-840\nif (isset($global['emailVerified'])) {\n    $this->emailVerified = $global['emailVerified'];\n}\nif (isset($global['canCreateMeet'])) {\n    $this->canCreateMeet = $global['canCreateMeet'];\n}\nif (isset($global['canStream'])) {\n    $this->canStream = $global['canStream'];\n}\nif (isset($global['canUpload'])) {\n    $this->canUpload = $global['canUpload'];\n}\n```\n\nNote that even though `userCreate.json.php:90` sets `canUpload` from the site's default configuration, `User::save()` subsequently overrides it with the attacker-controlled `$global` value.\n\nThe codebase already uses `self::isAPISecretValid()` to guard admin-only operations in other API methods (e.g., lines 294, 991, 1664, 2150), but this check is missing for the privilege parameters in `set_api_signUp`.\n\n## PoC\n\n```bash\n# Step 1: Get a CAPTCHA token\n# (Navigate to the signup page in a browser, solve the CAPTCHA, capture the token)\n\n# Step 2: Register with elevated privileges\ncurl -X POST 'https://target/plugin/API/set.json.php' \\\n  -d 'APIName=signUp' \\\n  -d 'user=attacker' \\\n  -d 'pass=Password123!' \\\n  -d 'email=attacker@example.com' \\\n  -d 'name=Attacker' \\\n  -d 'captcha=VALID_CAPTCHA_TOKEN' \\\n  -d 'emailVerified=1' \\\n  -d 'canUpload=1' \\\n  -d 'canStream=1' \\\n  -d 'canCreateMeet=1'\n\n# Expected: Account created with default (restricted) permissions\n# Actual: Account created with upload, stream, and meet permissions enabled,\n#         plus email marked as verified\n\n# Step 3: Verify elevated permissions by logging in and checking profile\ncurl -X POST 'https://target/plugin/API/set.json.php' \\\n  -d 'APIName=signIn' \\\n  -d 'user=attacker' \\\n  -d 'pass=Password123!'\n# Response will show canUpload=1, canStream=1, canCreateMeet=1, emailVerified=1\n```\n\n## Impact\n\n- **Email verification bypass:** Attackers can mark their accounts as email-verified without owning the email address, bypassing any email-gated functionality\n- **Unauthorized upload access:** Self-granted upload permissions allow uploading potentially malicious video content to the platform\n- **Unauthorized streaming access:** Self-granted streaming permissions allow unauthorized live streaming\n- **Unauthorized meeting creation:** Self-granted meet permissions allow creating meetings on the platform\n- **Policy bypass:** Platform administrators who intentionally restrict these permissions for new users (e.g., requiring manual approval before granting upload rights) have their access controls circumvented\n\n## Recommended Fix\n\nWrap the privilege parameter handling in an `isAPISecretValid()` check so that only admin-authenticated requests can set these values:\n\n```php\n// plugin/API/API.php — replace lines 4238-4249 with:\nif (self::isAPISecretValid()) {\n    if (isset($_REQUEST['emailVerified'])) {\n        $global['emailVerified'] = intval($_REQUEST['emailVerified']);\n    }\n    if (isset($_REQUEST['canCreateMeet'])) {\n        $global['canCreateMeet'] = intval($_REQUEST['canCreateMeet']);\n    }\n    if (isset($_REQUEST['canStream'])) {\n        $global['canStream'] = intval($_REQUEST['canStream']);\n    }\n    if (isset($_REQUEST['canUpload'])) {\n        $global['canUpload'] = intval($_REQUEST['canUpload']);\n    }\n}\n```",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "wwbn/avideo"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "29.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/WWBN/AVideo/security/advisories/GHSA-8j8m-p79x-g4jm"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/WWBN/AVideo/commit/061f242cba0e068cc1b461705fe839274b5038ff"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/WWBN/AVideo"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-862" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-06-22T17:25:03Z",
    "nvd_published_at" : null
  }
}