Jul 15, 2026·5 min read·4 visits
Authenticated Subsonic API users can exploit SSRF vectors in Koel <= 9.6.0 to scan internal networks, loopback interfaces, and cloud metadata resources via unvalidated podcast feed imports and redirect-following stream helpers.
A Server-Side Request Forgery (SSRF) vulnerability in the open-source personal music streaming server Koel allows authenticated Subsonic API users to perform unauthorized network queries. This flaw resides in both the Subsonic podcast feed import routine and the subsequent redirect handling inside the podcast streaming helper, exposing private local networks and internal loopback systems to unauthorized reconnaissance and interaction.
Koel is a personal audio streaming platform that supports a Subsonic-compatible API layer, allowing users to connect external clients. This API introduces a substantial attack surface, including endpoints designated for managing and parsing external podcast XML feeds.
A Server-Side Request Forgery (SSRF) vulnerability, categorized as CWE-918, exists in this functionality. An authenticated user possessing a standard Koel account and an active Subsonic API key can force the Koel application backend to execute HTTP requests to arbitrary systems.
This architecture exposes two distinct attack vectors. The first vector leverages the Subsonic podcast feed import routine, which processes remote feeds before verifying boundary safety. The second vector resides in the streaming helper service, which follows HTTP redirects without validating intermediate hops, allowing attackers to target internal systems or cloud metadata endpoints.
The first SSRF vector resides in the /rest/createPodcastChannel.view Subsonic API endpoint. The underlying request validation class, CreatePodcastChannelRequest.php, relies strictly on standard Laravel URL validation rules. This validation only asserts syntax correctness without restricting requests to loopback addresses, private IP ranges (RFC 1918), or link-local targets.
Once validated, the controller invokes PodcastService::addPodcast(), which initiates external feed parsing via Poddle::fromUrl(). Because the backend queries the target URL to extract the XML structure before checking for network boundaries, an attacker can exploit this endpoint to perform network reconnaissance. The application does validate episode enclosure URLs later during synchronization, but this defense-in-depth mechanism is executed after the initial SSRF vulnerability has already been triggered.
The second vector exists in PodcastService::getStreamableUrl(). While this helper applies a network safety check using Network::isSafeUrl($url) on the initial input, it fetches the resource using Guzzle with redirect following enabled. If an attacker passes an allowed external URL that redirects to a restricted local IP, Guzzle processes the redirect chain silently. The backend then extracts the destination from the Guzzle transfer history without executing a secondary safety check, bypassing the network boundary restrictions.
To resolve the Subsonic validation bypass, the patch integrates a custom SafeUrl validation rule directly into the request validation schema and adds service-layer checks.
// app/Http/Requests/Subsonic/CreatePodcastChannelRequest.php - BEFORE
public function rules(): array
{
return [
'url' => 'required|string|url'
];
}
// app/Http/Requests/Subsonic/CreatePodcastChannelRequest.php - AFTER
use App\Rules\SafeUrl;
public function rules(): array
{
return [
'url' => ['required', 'string', 'url', new SafeUrl()]
];
}Additionally, the service layer was updated to enforce boundary validation directly in the parsing pipeline before network operations occur:
// app/Services/Podcast/PodcastService.php (v9.7.0)
public function createParser(string $url): Parser
{
if (!Network::isSafeUrl($url)) {
throw new UnsafePodcastFeedUrlException($url);
}
return Poddle::fromUrl($url, SafeHttp::client());
}To remediate the redirect-following bypass, Koel replaced raw Guzzle client initializations with a specialized wrapper class named SafeHttp. This wrapper registers an on_redirect middleware callback. This middleware extracts each redirect URL, performs a safety check using Network::isSafeUrl(), and immediately aborts the connection if the target points to a restricted IP address range.
Exploitation requires an authenticated Koel account with access to the Subsonic API key. The attacker can identify this key in their profile settings or via application intercept logs.
In the first scenario, the attacker sets up an internal or external canary designed to log connections, or targets an internal service. The attacker then transmits an HTTP request to the Subsonic podcast creation API endpoint:
GET /rest/createPodcastChannel.view?apiKey=SUBSONIC_API_KEY&f=json&url=http://127.0.0.1:8103/feed.xml HTTP/1.1
Host: koel-target.localUpon receipt, the Koel server resolves the loopback IP and connects to port 8103. If the port is open and returns a valid XML feed, the application logs the registration. If the port is closed or does not host an XML file, the server returns an XML parsing exception. This discrepancy allows the attacker to map active ports and services on the internal network.
For the redirect-based attack, the attacker deploys a public redirection controller. When queried, this controller responds with a redirection header targeting the AWS metadata endpoint:
HTTP/1.1 302 Found
Location: http://169.254.169.254/latest/meta-data/The attacker requests this helper URL through the streaming endpoint, forcing Guzzle to retrieve credentials or metadata from the link-local address and expose the payload to the streaming stream.
The recommended remediation is upgrading the Koel deployment to version 9.7.0 or higher. This release contains patches for both the Subsonic input validation and the HTTP redirect-handling routine.
If upgrading is not immediately possible, apply network-level egress filtering. Configure the host's firewall, such as iptables, to block outbound connections originating from the Koel execution group to RFC 1918 blocks and loopback interfaces:
# Block local and loopback egress for the koel application process
iptables -A OUTPUT -m owner --uid-owner koel -d 127.0.0.0/8 -j REJECT
iptables -A OUTPUT -m owner --uid-owner koel -d 10.0.0.0/8 -j REJECT
iptables -A OUTPUT -m owner --uid-owner koel -d 172.16.0.0/12 -j REJECT
iptables -A OUTPUT -m owner --uid-owner koel -d 192.168.0.0/16 -j REJECT
iptables -A OUTPUT -m owner --uid-owner koel -d 169.254.169.254 -j REJECTAdditionally, implement WAF rules to inspect HTTP parameters. Filter incoming requests targeting /rest/createPodcastChannel.view and block entries where the url parameter contains string representations of private subnets or localhost domains.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
phanan/koel koel | <= 9.6.0 | 9.7.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-918 |
| Attack Vector | Network |
| CVSS | 6.4 |
| Impact | Blind SSRF, Internal Port Scanning, Information Disclosure |
| Exploit Status | PoC |
| KEV Status | Not Listed |
The product takes a user-supplied URL and retrieves it, permitting the application to make requests to unauthorized systems.
An authenticated Server-Side Request Forgery (SSRF) vulnerability in Koel, an open-source personal music streaming server, allows remote attackers to probe internal hosts and loopback addresses. The vulnerability arises due to a missing 'bail' validation rule in the Laravel-based form validation pipeline, which permits downstream HTTP checks to execute even after a URL has failed security verification.
CVE-2026-50661 is a security feature bypass vulnerability in Microsoft Windows BitLocker full-disk encryption. A physical attacker can exploit this flaw to bypass encryption controls, permitting unauthorized access to sensitive local storage and the modification of offline system configurations.
CVE-2026-56164 is a critical vulnerability affecting Microsoft SharePoint Server. It permits unauthenticated, remote attackers to bypass identity verification controls. This flaw is classified under CWE-306: Missing Authentication for Critical Function and allows elevation of privilege up to Farm Administrator level. The vulnerability has been added to CISA's Known Exploited Vulnerabilities catalog due to active exploitation.
A high-severity input sanitization and header injection vulnerability in TsDProxy allows authenticated Tailscale users to inject arbitrary values into the X-Forwarded-For and X-Real-IP HTTP headers. Because downstream backend services frequently trust these headers to resolve client identities, attackers can exploit this flaw to bypass IP-based access control lists, audit logs, and geo-blocking restrictions.
CVE-2026-54448 is a critical denial of service vulnerability in Trivy's Infrastructure-as-Code (IaC) misconfiguration scanning engine. Prior to version 0.71.0, Trivy utilized a custom archive parser to unpack Helm chart tarballs (.tgz) during automated scans. This custom implementation iterated through compressed files and loaded their entire raw contents into system memory using the io.ReadAll function without implementing size limits or threshold checks, enabling an attacker to trigger an immediate heap-allocation crash or system Out-of-Memory (OOM) termination using a decompression bomb.
A critical remote code execution vulnerability exists in TidGi Desktop up to version 0.13.0. The flaw allows an attacker to execute arbitrary code with Node.js privileges when a user imports or clones a malicious TiddlyWiki repository. This occurs due to the automatic execution of 'startup' modules defined in user-imported tiddler files.