CVE-2026-54492 Overview
CVE-2026-54492 is a Server-Side Request Forgery (SSRF) vulnerability in Koel, a free, open-source music streaming solution. The flaw exists in the Subsonic-compatible createPodcastChannel.view route in versions prior to 9.7.0. The app/Http/Requests/Subsonic/CreatePodcastChannelRequest.php request class does not apply the SafeUrl validation used by the regular podcast API. As a result, an authenticated attacker can submit a private URL that Koel fetches server-side during podcast channel creation. This enables blind internal request execution against loopback, Docker bridge, or RFC1918 HTTP destinations [CWE-918].
Critical Impact
An authenticated user can force the Koel server to issue HTTP requests to internal network destinations that would otherwise be unreachable from the public internet.
Affected Products
- Koel music streaming solution versions prior to 9.7.0
- Subsonic-compatible API endpoint createPodcastChannel.view
- Deployments exposing the Koel Subsonic API to authenticated users
Discovery Timeline
- 2026-08-19 - CVE-2026-54492 published to NVD
- 2026-08-20 - Last updated in NVD database
Technical Details for CVE-2026-54492
Vulnerability Analysis
The vulnerability resides in Koel's Subsonic-compatible podcast creation route. The regular podcast API applies a SafeUrl validation rule that rejects URLs pointing to internal network destinations. The Subsonic variant, defined in app/Http/Requests/Subsonic/CreatePodcastChannelRequest.php, omits this validation entirely.
When an authenticated request reaches app/Http/Controllers/Subsonic/CreatePodcastChannelController.php, the controller passes the unchecked URL to app/Services/Podcast/PodcastService.php. The PodcastService::addPodcast() method and its createParser() helper then invoke Poddle::fromUrl(), which triggers an immediate outbound HTTP request from the server. The impact is limited to blind SSRF because generic response-body exfiltration was not demonstrated through this route.
Root Cause
The root cause is inconsistent input validation between two functionally equivalent endpoints. The regular podcast API uses the SafeUrl rule to block requests targeting loopback, RFC1918, and other internal ranges. The Subsonic request class was implemented without that rule, leaving Poddle::fromUrl() to fetch any attacker-supplied URL.
Attack Vector
An authenticated user issues a Subsonic createPodcastChannel.view request containing a URL such as http://127.0.0.1:8080/, http://169.254.169.254/, or an RFC1918 address. Koel fetches the URL server-side during channel creation, allowing the attacker to probe internal services, cloud metadata endpoints, or Docker bridge networks.
// Security patch adding SSRF protection
// Source: https://github.com/koel/koel/commit/1331f335342b405e60ffabdd60f1f398508f996f
<?php
namespace App\Exceptions;
use RuntimeException;
final class UnsafePodcastFeedUrlException extends RuntimeException
{
public static function create(string $url): self
{
return new self("The podcast feed URL $url is not safe to fetch.");
}
}
The fix also imports the SafeUrl and HasAudioContentType validation rules into the Subsonic request classes:
// Source: https://github.com/koel/koel/commit/1331f335342b405e60ffabdd60f1f398508f996f
namespace App\Http\Requests\Subsonic;
use App\Http\Requests\Request;
use App\Rules\HasAudioContentType;
use App\Rules\SafeUrl;
Detection Methods for CVE-2026-54492
Indicators of Compromise
- Outbound HTTP requests from the Koel application process to loopback addresses (127.0.0.0/8), RFC1918 ranges, or Docker bridge networks (typically 172.17.0.0/16)
- Web server access logs containing POST or GET requests to /rest/createPodcastChannel.view with url parameters pointing to internal hosts
- Failed podcast channel creation records paired with unexpected outbound connections to cloud metadata endpoints such as 169.254.169.254
Detection Strategies
- Parse Koel HTTP access logs for createPodcastChannel.view requests and extract the url query parameter to flag internal IP ranges
- Correlate application-layer podcast creation events with egress connection telemetry from the host to identify SSRF probing patterns
- Alert on any process associated with the Koel PHP-FPM or web worker initiating connections to link-local or private address space
Monitoring Recommendations
- Deploy egress filtering telemetry that captures the destination IP and port of every outbound HTTP request made by the Koel application host
- Retain Subsonic API request logs with full URL parameters for at least 90 days to support retrospective hunting
- Baseline expected podcast feed destinations and alert on deviations to internal ranges
How to Mitigate CVE-2026-54492
Immediate Actions Required
- Upgrade Koel to version 9.7.0 or later, which applies the SafeUrl validation rule to the Subsonic podcast endpoint
- Restrict Subsonic API access to trusted authenticated users and remove unused API tokens
- Enforce egress network controls that block the Koel host from reaching loopback, RFC1918, and cloud metadata endpoints unless required
Patch Information
The vulnerability is fixed in Koel version 9.7.0. The patch is available in the GitHub commit 1331f335 and merged via pull request #2545. Full release details are documented in the GitHub Release v9.7.0 and the GitHub Security Advisory GHSA-w79m-f3jx-779v.
Workarounds
- Disable the Subsonic-compatible API in Koel configuration if it is not required by clients
- Place Koel behind a reverse proxy that blocks requests to /rest/createPodcastChannel.view from untrusted networks
- Configure host-level firewall rules to deny outbound traffic from the Koel process to internal network ranges and cloud metadata services
# Example egress restriction for the Koel host using iptables
iptables -A OUTPUT -m owner --uid-owner www-data -d 127.0.0.0/8 -j REJECT
iptables -A OUTPUT -m owner --uid-owner www-data -d 10.0.0.0/8 -j REJECT
iptables -A OUTPUT -m owner --uid-owner www-data -d 172.16.0.0/12 -j REJECT
iptables -A OUTPUT -m owner --uid-owner www-data -d 192.168.0.0/16 -j REJECT
iptables -A OUTPUT -m owner --uid-owner www-data -d 169.254.169.254/32 -j REJECT
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

