CVE-2025-64178 Overview
CVE-2025-64178 is a Server-Side Request Forgery (SSRF) vulnerability [CWE-918] in Jellysweep, a cleanup tool for the Jellyfin media server. The flaw exists in the /api/images/cache endpoint, which accepts a user-controlled url parameter and passes it directly to the internal cache package. An authenticated attacker can supply an arbitrary URL, causing the Jellysweep server to fetch content from any destination the server can reach. The vulnerability affects versions 0.12.1 and below and is resolved in version 0.13.0.
Critical Impact
Authenticated users can coerce the Jellysweep server into making outbound HTTP requests to attacker-chosen destinations, enabling internal network reconnaissance and abuse of trust boundaries.
Affected Products
- Jellysweep versions 0.12.1 and earlier
- Jellysweep deployments exposing the /api/images/cache endpoint
- Jellyfin media server environments integrated with vulnerable Jellysweep instances
Discovery Timeline
- 2025-11-06 - CVE-2025-64178 published to NVD
- 2026-04-15 - Last updated in NVD database
Technical Details for CVE-2025-64178
Vulnerability Analysis
The vulnerability resides in the ImageCache handler within internal/api/handler/handler.go. The handler read a url query parameter and forwarded it directly to GetImageCache().ServeImage(), which performed an outbound HTTP request to download the supplied resource. No allowlist, hostname validation, or scheme restriction was applied to the input.
Because the endpoint requires authentication, exploitation is limited to users who already possess valid Jellysweep credentials. However, in environments where account registration is open or where credentials are shared across media users, the attack surface remains significant. The server acts as a proxy, returning the fetched content to the caller through the cache response path.
Root Cause
The root cause is missing input validation on a user-supplied URL parameter passed to a server-side fetch operation. The handler trusted client input as the source identifier for the cache subsystem, violating SSRF defense guidance for [CWE-918]. The fix replaces the URL parameter with an internal numeric mediaID, removing user control over the outbound request destination entirely.
Attack Vector
An authenticated attacker issues a GET request to /api/images/cache?url=<attacker-controlled-URL>. The Jellysweep server then performs an HTTP request to the supplied URL from its own network context. This enables probing of internal services, cloud instance metadata endpoints, and other hosts that would normally be unreachable from the attacker's network position.
// Vulnerable handler (pre-patch) and the applied fix
// internal/api/handler/handler.go
// ImageCache serves cached images or downloads them if not cached.
func (h *Handler) ImageCache(c *gin.Context) {
- imageURL := c.Query("url")
- if imageURL == "" {
- c.JSON(http.StatusBadRequest, gin.H{"error": "url parameter is required"})
+ mediaID, err := parseUintParam(c.Query("id"))
+ if err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": "invalid or missing id parameter"})
return
}
// Serve the cached image
- err := h.engine.GetImageCache().ServeImage(c.Request.Context(), imageURL, c.Writer, c.Request)
+ err = h.engine.GetImageCache().ServeImage(c.Request.Context(), mediaID, c.Writer, c.Request)
if err != nil {
// Error is already handled in ServeImage
return
Source: GitHub Commit 17466312510966418aea941e4944229856d55101
The converter model was also updated to remove the externally exposed PosterURL field, eliminating the upstream URL leak that enabled URL-based cache lookups.
Detection Methods for CVE-2025-64178
Indicators of Compromise
- Requests to /api/images/cache containing a url query parameter pointing to non-Jellyfin hosts, internal RFC1918 ranges, localhost, or 169.254.169.254.
- Outbound HTTP connections from the Jellysweep process to destinations outside the configured Jellyfin server.
- Unusually high request volume to /api/images/cache from a single authenticated session.
Detection Strategies
- Inspect Jellysweep access logs for url= query strings on the image cache endpoint and decode the values to identify suspicious targets.
- Monitor process-level network telemetry on the Jellysweep host for outbound connections to internal subnets, cloud metadata IPs, or non-standard ports.
- Alert on HTTP responses returned by /api/images/cache whose Content-Type does not match expected image MIME types.
Monitoring Recommendations
- Forward Jellysweep application logs and host network flows to a centralized analytics platform for correlation.
- Baseline normal poster-download traffic and flag deviations in destination host, port, and scheme.
- Track authenticated session identifiers issuing image cache requests to identify compromised or abusive accounts.
How to Mitigate CVE-2025-64178
Immediate Actions Required
- Upgrade Jellysweep to version 0.13.0 or later, which removes the user-controlled URL parameter from the image cache endpoint.
- Audit Jellysweep user accounts and rotate credentials for any accounts that may have been shared or exposed.
- Review recent access logs for /api/images/cache?url= requests and investigate any non-Jellyfin destinations.
Patch Information
The fix is contained in commit 17466312510966418aea941e4944229856d55101 and shipped in Jellysweep 0.13.0. The handler now accepts an internal id parameter that maps to a known media record, removing the ability for clients to specify arbitrary outbound URLs. See the GitHub Security Advisory GHSA-xc93-q32j-cpcg for the official disclosure.
Workarounds
- Restrict network egress from the Jellysweep host to only the Jellyfin server and required external services using host or network firewall rules.
- Place Jellysweep behind a reverse proxy that strips or rejects the url query parameter on /api/images/cache until upgrading is possible.
- Limit Jellysweep account creation and enforce strong authentication to reduce the pool of users able to invoke the vulnerable endpoint.
# Example egress restriction using iptables on the Jellysweep host
# Allow outbound traffic only to the Jellyfin server (replace IP) and DNS
iptables -A OUTPUT -d 10.0.0.10 -p tcp --dport 8096 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -j REJECT
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

