CVE-2026-35586
pyLoad auth bypass allows non-admins to change SSL certificate/key paths.
- CVSS 6.8
- CWE-863
- Authentication, Authorization, and Session Management
- Remote
pyLoad is a free and open-source download manager written in Python. Prior to 0.5.0b3.dev97, the ADMIN_ONLY_CORE_OPTIONS authorization set in set_config_value() uses incorrect option names ssl_cert and ssl_key, while the actual configuration option names are ssl_certfile and ssl_keyfile. This name mismatch causes the admin-only check to always evaluate to False, allowing any user with SETTINGS permission to overwrite the SSL certificate and key file paths. Additionally, the ssl_certchain option was never added to the admin-only set at all. This vulnerability is fixed in 0.5.0b3.dev97.
- CWE
- CWE-863
- CVSS base score
- 6.8
- Published
- 2026-04-07
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Assignment
- Code defect classification
- Incorrect Check
- Category
- Authentication, Authorization, and Session Management
- Subcategory
- Security Misconfigurations
- Accessibility scope
- Remote
- Impact
- Privilege Escalation
- Affected component
- pyLoad
- Fixed by upgrading
- Yes
Solution
Upgrade to pyLoad version 0.5.0b3.dev97 or later.
Vulnerable code sample
ADMIN_ONLY_CORE_OPTIONS = {
"ip",
"port",
"use_ssl",
"ssl_cert",
"ssl_key",
}
def set_config_value(config, option, value, is_admin, has_settings_permission):
"""
Represents the vulnerable logic that sets a configuration value.
The actual implementation was a class method within pyLoad's Core.
"""
if not has_settings_permission:
# In the real application, this would raise an authorization error
# if the user does not have the 'SETTINGS' role.
raise PermissionError("User lacks necessary permissions to change settings.")
# This is the vulnerable authorization check.
# A non-admin can change 'ssl_certfile' and 'ssl_keyfile' because
# those strings are not present in ADMIN_ONLY_CORE_OPTIONS.
# The 'ssl_certchain' option is also missing from the set entirely.
if option in ADMIN_ONLY_CORE_OPTIONS and not is_admin:
raise PermissionError("This option can only be changed by an administrator.")
# If the check above is bypassed, the configuration value is updated.
config[option] = valuePatched code sample
import sys
# A mock user class for demonstration purposes.
class MockUser:
def __init__(self, is_admin=False):
# In a real application, this would check user roles and permissions.
self.permissions = {'SETTINGS'}
if is_admin:
self.permissions.add('ADMIN')
def has_permission(self, permission_name):
return permission_name in self.permissions
# This code represents a simplified version of the relevant pyLoad module
# after the vulnerability has been patched.
class PatchedConfigManager:
"""
A code example representing the fix for CVE-2026-35586.
The vulnerability existed because the ADMIN_ONLY_CORE_OPTIONS set
contained incorrect names ('ssl_cert', 'ssl_key') and was missing
'ssl_certchain'. This allowed any user with SETTINGS permission to
modify these sensitive options.
The fix involves correcting the option names to 'ssl_certfile' and
'ssl_keyfile' and adding 'ssl_certchain' to the set, ensuring
the admin-only check works as intended.
"""
# VULNERABILITY FIX:
# The option names 'ssl_cert' and 'ssl_key' have been corrected to
# 'ssl_certfile' and 'ssl_keyfile'. The 'ssl_certchain' option has been added.
# This ensures these sensitive options require admin privileges to be modified.
ADMIN_ONLY_CORE_OPTIONS = {
"folder",
"chunks",
"min_free_space",
"max_downloads",
"language",
"proxy_url",
"proxy_port",
"proxy_user",
"proxy_pass",
"proxy_socks5",
"ssl_certfile", # Corrected from 'ssl_cert'
"ssl_keyfile", # Corrected from 'ssl_key'
"ssl_certchain" # Added to the admin-only set
}
def __init__(self):
# A mock configuration dictionary
self.config = {
"ssl_certfile": "/etc/pyload/ssl.crt",
"ssl_keyfile": "/etc/pyload/ssl.key",
"ssl_certchain": "",
"language": "en"
}
def set_config_value(self, user, option, value):
"""
Sets a configuration value, performing authorization checks.
This method now correctly protects admin-only SSL settings.
"""
# A user must at least have SETTINGS permission
if not user.has_permission('SETTINGS'):
raise PermissionError("User does not have SETTINGS permission.")
# This check is the core of the security control. Because the option names
# in ADMIN_ONLY_CORE_OPTIONS are now correct, this check will no longer
# fail for SSL-related options.
if option in self.ADMIN_ONLY_CORE_OPTIONS:
if not user.has_permission('ADMIN'):
# This code block is now correctly triggered for non-admins
# trying to change 'ssl_certfile', 'ssl_keyfile', or 'ssl_certchain'.
raise PermissionError(
f"Admin privileges required to change core option '{option}'."
)
# If authorization passes, the value is set.
print(f"Authorization successful. Setting '{option}' to '{value}'.")
self.config[option] = value
if __name__ == '__main__':
# --- Demonstration of the fix ---
manager = PatchedConfigManager()
admin_user = MockUser(is_admin=True)
normal_user = MockUser(is_admin=False)
print("--- Simulating a non-admin user ---")
# 1. Attempt to change a regular setting (should succeed)
try:
print("\nAttempting to change 'language'...")
manager.set_config_value(normal_user, "language", "de")
except PermissionError as e:
print(f"Error: {e}", file=sys.stderr)
# 2. Attempt to change 'ssl_keyfile' (should be blocked by the fix)
try:
print("\nAttempting to change 'ssl_keyfile'...")
manager.set_config_value(normal_user, "ssl_keyfile", "/tmp/malicious_key.pem")
except PermissionError as e:
print(f"SUCCESS (FIX DEMONSTRATED): Operation correctly blocked. Error: {e}")
# 3. Attempt to change 'ssl_certchain' (should be blocked by the fix)
try:
print("\nAttempting to change 'ssl_certchain'...")
manager.set_config_value(normal_user, "ssl_certchain", "/tmp/malicious_chain.pem")
except PermissionError as e:
print(f"SUCCESS (FIX DEMONSTRATED): Operation correctly blocked. Error: {e}")
print("\n\n--- Simulating an admin user ---")
# 4. Admin user attempts to change 'ssl_keyfile' (should succeed)
try:
print("\nAttempting to change 'ssl_keyfile'...")
manager.set_config_value(admin_user, "ssl_keyfile", "/etc/pyload/new_ssl.key")
except PermissionError as e:
print(f"Error: {e}", file=sys.stderr)
print("\nFinal configuration:", manager.config)Payload
{
"section": "core",
"option": "ssl_keyfile",
"value": "/path/to/attacker/controlled/key.pem"
}
Cite this entry
@misc{vaitp:cve202635586,
title = {{pyLoad auth bypass allows non-admins to change SSL certificate/key paths.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-35586},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-35586/}}
}
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 ::
