Severity by source
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Primary rating from NVD · only source for this CVE.
CVSS VectorNVD
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Lifecycle Timeline
3DescriptionCVE.org
MoviePilot v2 contains a server-side request forgery vulnerability in the image proxy endpoint that allows authenticated attackers to request arbitrary URLs by supplying a resource_token cookie and a URL whose domain matches the assembled allowlist. Attackers can bypass internal network protections because the SecurityUtils.is_safe_url function performs only domain-membership checking without blocking private, loopback, or link-local addresses, enabling enumeration of internal services such as Jellyfin, Emby, or Plex and exfiltration of data from internal network resources.
Articles & Coverage 1
AnalysisAI
Server-side request forgery in MoviePilot v2's image proxy endpoint (/api/v1/system/img-proxy) allows authenticated attackers holding a valid resource_token cookie to coerce the server into fetching arbitrary internal URLs. The flaw stems from SecurityUtils.is_safe_url performing domain-membership checks without blocking private, loopback, or link-local IPs, letting attackers enumerate co-hosted media services such as Jellyfin, Emby, and Plex and exfiltrate internal data. No public exploit identified at time of analysis, though the upstream patch and vendor-published advisory clearly document the attack path.
Technical ContextAI
MoviePilot is a self-hosted media automation/aggregation tool (cpe:2.3:a:jxxghp:moviepilot) commonly deployed alongside Jellyfin, Emby, or Plex on home/lab networks. The vulnerable code path is the FastAPI fetch_image endpoint in app/api/endpoints/system.py, which proxies arbitrary URLs after a call to SecurityUtils.is_safe_url in app/utils/security.py. The root cause is a classic CWE-918 (SSRF) pattern: the allowlist validator only compared the parsed hostname against an assembled domain set and never resolved the hostname to an IP nor inspected the resulting address class, so DNS entries or literal IPs pointing at RFC1918, 127.0.0.0/8, 169.254.0.0/16, or other non-global ranges that happened to be in the allowlist (or that resolved into it) would be approved. The patch adds a block_private flag and a new _is_global_hostname helper that uses ipaddress and socket.getaddrinfo to reject any host whose resolution yields a non-global address.
RemediationAI
Vendor-released patch: upgrade to MoviePilot v2.13.2 or later (https://github.com/jxxghp/MoviePilot/releases/tag/v2.13.2), which introduces the block_private=True path through SecurityUtils.is_safe_url so that hostnames resolving to private, loopback, or link-local addresses are refused even when their domain is on the allowlist. If immediate upgrade is not possible, restrict reachability of the /api/v1/system/img-proxy endpoint at a reverse proxy (deny external POSTs/GETs to that path or require an additional auth layer), rotate or invalidate resource_token cookies issued to untrusted users, and place MoviePilot in an egress-restricted network namespace that blocks outbound traffic to RFC1918, 127.0.0.0/8, and 169.254.0.0/16 - note that namespace-level egress filtering will also break any legitimate proxying to co-hosted media servers on the same LAN, so verify integrations afterward. Review the VulnCheck advisory and GitHub issue #5823 for additional indicators.
More in Moviepilot
View allSame weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-33364
GHSA-4hhq-38m9-mgg7