CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-6qvr-wjmv-v8mm: Koel: Incomplete fix for CVE-2026-47260 — systemic SSRF in podcast & radio fetch paths

highCVSS 7.1CVE-2026-54491
Summary The fix for CVE-2026-47260 (v9.3.5) added an initial isSafeUrl() check to several fetchers (synchronizeEpisodes, getStreamableUrl, AddRadioStation, EpisodePlayable), but the redirect-target validation — the per-hop Guzzle on_redirect callback added in follow-up commit be1e867 — was applied to only one path, EpisodePlayable. Every other server-side fetcher therefore has only the initial check, which an HTTP 302 redirect to an internal address bypasses, or no check at all. DNS rebinding (validation and connection resolve DNS separately, with no IP pinning) bypasses the initial check on every path. An authenticated, non-admin user can thus cause the Koel server to issue requests to arbitrary internal / cloud-metadata endpoints (SSRF) by supplying a URL on an attacker-controlled host that 302-redirects to an internal address. Note: commit be1e867 shows the redirect-based SSRF vector was recognised, but the redirect defense was applied to a single call site rather than generalised — so the class survives in the sibling paths below. Details — Root cause App\Helpers\Network::isPublicHost() / isSafeUrl() perform a point-in-time host check with no pinning of the resolved IP, and per-redirect-hop re-validation exists only in App\Values\Podcast\EpisodePlayable (the on_redirect callback from commit be1e867). Consequently every other fetcher is exposed to (1) redirect SSRF — initial URL passes isSafeUrl, then the HTTP client follows a cross-host 302 to an internal target without re-validating the hop; and (2) DNS rebinding (TOCTOU) — isPublicHost resolves DNS at validation, the HTTP client resolves again at connect time. Affected paths (all reachable by any authenticated user) | # | Location | Issue | |---|----------|-------| | 1 | PhanAn\Poddle\Poddle::fromUrl() → Http::timeout()->get($url) (used by PodcastService::addPodcast/refreshPodcast) | Plain Http::get, follows redirects, no per-hop validation; refreshPodcast does not re-run isSafeUrl at all | | 2 | Podcas

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
high — CVSS 7.1
Published
2026-07-15
Last updated
2026-07-15
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-6qvr-wjmv-v8mm

Referenced CVEs

CVECSIRTS overviewExternal
CVE-2026-54491coverage & exploitation statusNVD · CVE.org

More from GitHub Security Advisories