GitHub Security Advisory: GHSA-pq8p-wc4f-vg7j
Package: wwbn/avideo (COMPOSER)
Severity: HIGH (CVSS 9.3)
CWE: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
Vulnerable versions: <= 29.0
Patched in: unpatched

Summary: WWBN AVideo has an incomplete fix for CVE-2026-33502: Command Injection

Details:
### Summary

The incomplete fix for AVideo's `test.php` adds `escapeshellarg` for wget but leaves the `file_get_contents` and `curl` code paths unsanitized, and the URL validation regex `/^http/` accepts strings like `httpevil.com`.

### Affected Package

- **Ecosystem:** Other
- **Package:** AVideo
- **Affected versions:** < commit 1e6cf03e93b5
- **Patched versions:** >= commit 1e6cf03e93b5

### Details

The vulnerable `wget()` function in `plugin/Live/test.php`:

```php
function wget($url, $filename) {
    $cmd = "wget --tries=1 {$url} -O {$filename} --no-check-certificate";
    exec($cmd);
}
```

Neither `$url` nor `$filename` is passed through `escapeshellarg()`. The URL validation uses `preg_match("/^http/", $url)` which:
- Does not require `://` (matches `httpevil.com`)
- Does not block shell metacharacters (`;`, backticks, `$()`)
- Does not validate the URL is actually a URL

A payload like `http://x; id > /tmp/pwned; echo ` passes the regex and injects arbitrary commands via the semicolons.

The fix adds `escapeshellarg()` for the wget path and an `isAllowedStatsTestURL` allowlist, but `url_get_contents()` (used by the same endpoint) still follows redirects without validation. The wget-specific fix does not protect the `file_get_contents` and `curl` code paths that handle the same user-supplied URL.

### PoC

```python
"""
CVE-2026-33502 - Command injection in AVideo plugin/Live/test.php

Tests REAL vulnerable code from:
  plugin/Live/test.php (commit pre-1e6cf03)

The vulnerable wget() function at the end of test.php:
  $cmd = "wget --tries=1 {$url} -O {$filename} --no-check-certificate";
  exec($cmd);

No escapeshellarg() is used on $url or $filename parameters.
The URL validation regex /^http/ is also weak (matches "httpevil.com").
"""

import re
import sys
import os
import subprocess

src_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'src')
src_content = open(os.path.join(src_dir, 'test.php')).read()

print("=" * 60)
print("CVE-2026-33502: AVideo Command Injection PoC (Real Source)")
print("=" * 60)
print()

has_weak_regex = bool(re.search(r'preg_match\("/\^http/"', src_content))
has_unsanitized_wget = 'wget --tries=1 {$url} -O {$filename}' in src_content
has_escapeshellarg = 'escapeshellarg' in src_content
has_exec = 'exec($cmd)' in src_content
has_auth_check = 'User::isAdmin()' in src_content

print("[*] Source: plugin/Live/test.php (pre-fix)")
print("[*] Weak URL regex /^http/: " + str(has_weak_regex))
print("[*] Unsanitized wget command: " + str(has_unsanitized_wget))
print("[*] escapeshellarg used: " + str(has_escapeshellarg))
print("[*] exec() used: " + str(has_exec))
print("[*] Authentication check: " + str(has_auth_check))
print()

def extract_wget_function():
    match = re.search(r'function wget\(.*?\n\}', src_content, re.DOTALL)
    if match:
        return match.group(0)
    return None

wget_func = extract_wget_function()
if wget_func:
    print("[*] Extracted real wget function:")
    for line in wget_fu