Severity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
Network-reachable endpoint requiring authenticated low-privilege user (PR:L); SSRF via HEAD/GET enables internal network probing (C:L) with minor side-effect risk on internal services (I:L); availability impact not substantiated for read-only HTTP requests.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
Lifecycle Timeline
3DescriptionCVE.org
Koel is a free, open-source music streaming solution. Prior to version 9.7.1, Koel contains a Server-Side Request Forgery (SSRF) vulnerability in the radio station creation endpoint (POST /api/radio/stations). The url field validation rules are declared without the bail keyword, so the HasAudioContentType rule - which issues HTTP requests to the supplied URL - still executes even after the SafeUrl rule has rejected the URL as pointing to a private/reserved address. Any authenticated, non-admin user can therefore coerce the server into making HEAD/GET requests to arbitrary internal hosts. This issue has been patched in version 9.7.1.
AnalysisAI
SSRF in Koel's radio station creation endpoint (POST /api/radio/stations) allows any authenticated non-admin user to coerce the server into issuing HEAD/GET requests to arbitrary internal hosts. The root cause is a missing Laravel bail keyword in the URL field validation chain: the SafeUrl rule correctly rejects private/reserved addresses, but without bail, the subsequent HasAudioContentType rule still executes and makes an outbound HTTP request to the attacker-supplied URL. Vendor-released patch version 9.7.1 resolves the issue; no public exploit or CISA KEV listing exists at time of analysis.
Technical ContextAI
Koel is a PHP/Laravel-based music streaming application. The affected endpoint is POST /api/radio/stations, which accepts a url field for internet radio streams. Laravel's validation pipeline by default executes all declared rules in sequence unless the bail modifier is prepended, which stops further rule evaluation on the first failure. The SafeUrl rule performs DNS-based checks to reject URLs resolving to private or reserved IP ranges (RFC 1918, loopback, link-local) without making network connections. The HasAudioContentType rule, however, issues a live HTTP HEAD or GET request to validate audio content type. Without bail, HasAudioContentType fires regardless of SafeUrl's rejection, constituting a classic SSRF bypass of input validation (CWE-918). Affected products per CPE: cpe:2.3:a:koel:koel:*:*:*:*:*:*:*:* covering all versions prior to 9.7.1. The commit diff also removes Network.php and SafeHttp.php helper classes previously used for SSRF-safe redirect validation, indicating a broader refactor of the outbound HTTP defense surface alongside the primary fix.
RemediationAI
Upgrade Koel to version 9.7.1, which resolves the issue by adding the bail modifier to the URL field validation rules in app/Ai/Tools/AddRadioStation.php, ensuring that HasAudioContentType never executes when SafeUrl has already rejected a private or reserved URL. The exact fix commit is available at https://github.com/koel/koel/commit/5f6ce2cefd08f437a269236b677ad971517ccbb6. If immediate upgrade is not possible, a targeted workaround is to restrict access to the POST /api/radio/stations endpoint at the application firewall or reverse-proxy layer for untrusted user roles, accepting the trade-off that radio station creation will be unavailable for those users. Network-level egress filtering on the Koel server host to block outbound connections to RFC 1918, loopback (127.0.0.0/8), and link-local (169.254.0.0/16) ranges will also contain the SSRF reach without disabling the feature, though this should be considered defense-in-depth rather than a primary fix. Vendor advisory: https://github.com/koel/koel/security/advisories/GHSA-jr4p-4xjh-fwvw.
Same weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-36546
GHSA-jr4p-4xjh-fwvw