Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-50552

CVE-2026-50552: Koel Music Streaming SSRF Vulnerability

CVE-2026-50552 is a Server-Side Request Forgery flaw in Koel that allows authenticated users to make unauthorized requests to internal hosts. This article covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-50552 Overview

CVE-2026-50552 is a Server-Side Request Forgery (SSRF) vulnerability in Koel, a free and open-source music streaming solution. The flaw exists in the radio station creation endpoint (POST /api/radio/stations) in versions prior to 9.7.1. The url field validation rules omit the bail keyword, so the HasAudioContentType rule continues to execute even after the SafeUrl rule rejects a URL pointing to a private or reserved address. Any authenticated, non-admin user can coerce the server into issuing HEAD or GET requests to arbitrary internal hosts. The issue is tracked under [CWE-918] and was patched in version 9.7.1.

Critical Impact

Authenticated low-privilege users can pivot through the Koel server to reach internal services, metadata endpoints, and other reserved network ranges.

Affected Products

  • Koel music streaming solution versions prior to 9.7.1
  • Self-hosted Koel deployments exposing the radio station API
  • Koel instances accessible to non-admin authenticated users

Discovery Timeline

  • 2026-06-12 - CVE-2026-50552 published to NVD
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2026-50552

Vulnerability Analysis

Koel exposes a radio station creation endpoint that accepts a url field. The endpoint applies a Laravel validation chain that includes a custom SafeUrl rule and a HasAudioContentType rule. The SafeUrl rule resolves the host and rejects URLs that point to private, loopback, or reserved address ranges. The HasAudioContentType rule issues an outbound HTTP request to verify the response content type.

Because the validator omits the bail keyword, Laravel continues evaluating subsequent rules after a prior rule fails. When SafeUrl rejects a private address, the HasAudioContentType rule still fires and performs the HTTP request anyway. The server then issues HEAD or GET requests against attacker-controlled URLs, including internal services, cloud metadata endpoints, and other hosts that are otherwise unreachable.

Root Cause

The root cause is missing short-circuit validation. Laravel evaluates validation rules sequentially but does not stop on first failure unless the bail rule is present. The original rule set declared required and url checks alongside SafeUrl and HasAudioContentType, but never told the validator to stop. The fix prepends bail to the rule array so that failure of SafeUrl prevents HasAudioContentType from running.

Attack Vector

An authenticated, non-admin user submits a POST /api/radio/stations request with a url value pointing to an internal resource such as http://127.0.0.1, http://169.254.169.254/latest/meta-data/, or an IPv6 link-local address. Although the API returns a validation error, the server still issues an outbound request to the supplied URL, enabling reconnaissance of internal infrastructure and interaction with services that trust the Koel host.

php
$validator = Validator::make(['url' => $request['url']], [
    'url' => [
+       'bail',
        'required',
        'url',
        Rule::unique('radio_stations')->where(static fn (Builder $query) => $query->where('user_id', $userId)),
        // ... SafeUrl and HasAudioContentType rules follow
    ],
]);
// Source: https://github.com/koel/koel/commit/5f6ce2cefd08f437a269236b677ad971517ccbb6

The patch adds bail so validation halts on the first failed rule, preventing HasAudioContentType from making the outbound request after SafeUrl rejects the host.

Detection Methods for CVE-2026-50552

Indicators of Compromise

  • Outbound HEAD or GET requests from the Koel application server to RFC1918, loopback, or link-local addresses
  • Repeated POST /api/radio/stations requests from non-admin accounts that return validation errors
  • Application logs showing HasAudioContentType rule execution against URLs that also triggered SafeUrl failures
  • Outbound requests to cloud metadata endpoints such as 169.254.169.254 from the Koel host

Detection Strategies

  • Inspect web access logs for POST /api/radio/stations activity correlated with internal-host destinations in egress logs
  • Hunt for outbound HTTP requests originating from the Koel application user-agent toward non-routable ranges
  • Alert on validation failure responses paired with successful outbound DNS resolution of the submitted hostname

Monitoring Recommendations

  • Forward Koel application logs and host network telemetry to a centralized analytics platform for correlation
  • Monitor egress traffic from the Koel server using deny-by-default rules and alert on policy violations
  • Track per-user request rates against /api/radio/stations to identify scanning behavior

How to Mitigate CVE-2026-50552

Immediate Actions Required

  • Upgrade Koel to version 9.7.1 or later, which adds the bail rule and removes vulnerable network helpers
  • Restrict outbound network access from the Koel application server using egress firewall rules
  • Revoke or audit non-admin accounts created during the exposure window and review radio station entries
  • Block access to cloud metadata endpoints from the Koel host with explicit deny rules

Patch Information

The fix is included in Koel 9.7.1. See the GitHub Security Advisory and the GitHub Commit Details for the complete change set, which also addresses related DNS rebinding and IPv6 transition issues.

Workarounds

  • Place the Koel server behind an egress proxy that enforces an allowlist of permitted destinations
  • Disable or restrict the radio station feature for non-admin users until patching is complete
  • Block outbound traffic from the Koel host to RFC1918, loopback, link-local, and IPv6 reserved ranges
bash
# Example iptables egress restriction for the Koel host
iptables -A OUTPUT -d 127.0.0.0/8 -j REJECT
iptables -A OUTPUT -d 10.0.0.0/8 -j REJECT
iptables -A OUTPUT -d 172.16.0.0/12 -j REJECT
iptables -A OUTPUT -d 192.168.0.0/16 -j REJECT
iptables -A OUTPUT -d 169.254.0.0/16 -j REJECT
ip6tables -A OUTPUT -d ::1/128 -j REJECT
ip6tables -A OUTPUT -d fc00::/7 -j REJECT
ip6tables -A OUTPUT -d fe80::/10 -j REJECT

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.