Severity by source
AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N
Lifecycle Timeline
2DescriptionGitHub Advisory
Summary
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 option ("general", "ssl_verify") is not on that allowlist. Any authenticated user with the non-admin SETTINGS permission can set general.ssl_verify = off, and every subsequent outbound pycurl request is made with SSL_VERIFYPEER=0 and SSL_VERIFYHOST=0 - TLS peer and hostname verification are fully disabled. An on-path attacker can then present forged certificates for any hostname pyload fetches.
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.
Details
Writer - src/pyload/core/api/__init__.py, set_config_value() (around lines 215-290). The function is decorated with @permission(Perms.SETTINGS) and only rejects writes when (category, option) appears in ADMIN_ONLY_CORE_OPTIONS:
ADMIN_ONLY_CORE_OPTIONS = {
("general", "storage_folder"),
("log", "syslog_host"), ("log", "syslog_port"),
("proxy", "password"), ("proxy", "username"),
("reconnect", "script"),
("webui", "host"),
("webui", "ssl_certfile"), ("webui", "ssl_keyfile"), ("webui", "ssl_certchain"),
("webui", "use_ssl"),
}
...
if (category, option) in ADMIN_ONLY_CORE_OPTIONS and not is_admin:
self.pyload.log.error(...); return
self.pyload.config.set(category, option, value)("general", "ssl_verify") is absent. config.set() in src/pyload/core/config/parser.py:329 calls cast() which has no branch for enum-string types - "off" is stored verbatim and persisted to disk via self.save().
Reader - src/pyload/core/network/request_factory.py:109-110:
def get_options(self):
return {
"interface": self.iface(),
"proxies": self.get_proxies(),
"ipv6": self.pyload.config.get("download", "ipv6"),
"ssl_verify": self.pyload.config.get("general", "ssl_verify"),
...
}Sink - src/pyload/core/network/http/http_request.py:193-206:
if "ssl_verify" in options:
aiachaser_on = b"on (using aia-chaser)"
if options["ssl_verify"] in [True, b"on", aiachaser_on]:
...
ssl_verify = 1
else:
ssl_verify = 0
self.c.setopt(pycurl.SSL_VERIFYPEER, ssl_verify)
self.c.setopt(pycurl.SSL_VERIFYHOST, ssl_verify * 2)Because get_options() is invoked every time a new pycurl handle is built, the new config value takes effect on the very next outbound request - no pyload restart required.
PoC
Authenticated as any user who has Perms.SETTINGS but is not admin (e.g. a user with Role.USER + the SETTINGS permission bit):
# 1) Log in as the SETTINGS (non-admin) user.
curl -c cookies.txt -X POST http://pyload.example:8000/api/login \
-d 'username=settings_user&password=<password>'
# 2) Disable TLS verification for all outbound downloads.
curl -b cookies.txt -X POST http://pyload.example:8000/api/setConfigValue \
-d 'category=general&option=ssl_verify&value=off§ion=core'
# -> 200 OK. Config persisted.
# 3) Enqueue any HTTPS download. An on-path attacker (shared LAN,
# compromised upstream router, DNS hijack, or a malicious proxy
# enabled via the sibling advisory on the proxy.* options) can
# now present a forged cert for any target - pyload accepts it.Verification: observe pycurl SSL_VERIFYPEER=0 in a debug build, or confirm that a download from an HTTPS endpoint served with a self-signed / mismatched cert succeeds after step 2 and fails before it.
Impact
- Who: any authenticated user whose role was granted
Perms.SETTINGS. In multi-user pyload deployments that delegate settings administration to non-admins, this is an unintended privilege escalation from "can change UI/download settings" to "can silently disable TLS cert validation for all outbound fetches". - What:
- Man-in-the-middle on all HTTPS downloads, captcha fetches, update checks, and plugin HTTP calls.
- Extends the impact of the already-published SSRF chain (CVE-2026-33992 / CVE-2026-35459). The URL-hostname validation those patches added is only meaningful if the TLS channel authenticates the endpoint; with
ssl_verify=off, an on-path attacker can present forged certs for already-validated hosts - so HTTPS cloud-metadata endpoints and internal HTTPS services behind the host allowlist become reachable again. - Silent to the admin. Every adjacent security-critical option (
proxy.password, SSL certfile/keyfile/certchain,use_ssl) is already admin-only, so the admin's mental model is that TLS policy cannot be weakened by a non-admin.
- Not impacted: unauthenticated attackers; users holding only
DOWNLOAD/LISTroles.
AnalysisAI
Non-admin users holding the SETTINGS permission in pyload-ng can disable TLS peer and hostname verification by setting general.ssl_verify=off via the set_config_value() API, enabling man-in-the-middle attacks on all outbound HTTPS requests including downloads, captcha fetches, and plugin calls. This is an incomplete fix for a series of prior allowlist bypasses (CVE-2026-33509, CVE-2026-35463, CVE-2026-35464, CVE-2026-35586) in which security-sensitive configuration options were omitted from the ADMIN_ONLY_CORE_OPTIONS allowlist.
Technical ContextAI
The vulnerability lies in pyload-ng's configuration API authorization model, which uses a hand-maintained allowlist (ADMIN_ONLY_CORE_OPTIONS) in src/pyload/core/api/__init__.py to restrict which config options can be modified by non-admin users holding the SETTINGS permission. The ssl_verify option, which controls pycurl's SSL_VERIFYPEER and SSL_VERIFYHOST flags, was not included on this allowlist despite its security-critical nature. When set_config_value() is called with category='general' and option='ssl_verify', the value bypasses permission checks and is persisted to disk. Subsequently, every new HTTP request handler instantiation calls get_options() to retrieve the config value and applies it directly to the pycurl handle via setopt(pycurl.SSL_VERIFYPEER, ssl_verify * 2), allowing an on-path attacker to intercept HTTPS connections with forged certificates. The root cause is CWE-295 (Improper Certificate Validation), compounded by an incomplete authorization allowlist (CWE-639). This vulnerability is part of a recurring pattern where configuration options are added to the allowlist reactively rather than by secure default.
RemediationAI
Upgrade pyload-ng to version 0.5.0b3.dev100 or later, which adds ('general', 'ssl_verify') to the ADMIN_ONLY_CORE_OPTIONS allowlist in src/pyload/core/api/__init__.py. This patch prevents non-admin SETTINGS users from modifying SSL verification settings. As a temporary compensating control, restrict the SETTINGS permission to trusted administrators only, and audit current role assignments to ensure no untrusted users hold this permission. Monitor pyload configuration files (typically ~/.pyload/core.conf or similar) for manual edits that set ssl_verify=off, as an already-compromised account could have modified the config file directly. If using pyload-ng in a multi-user environment where non-admin settings delegation is required, do not assign the SETTINGS permission until the patch is applied. Note that this mitigation requires restricting delegation functionality, which may reduce administrator productivity; the patch is the only complete fix. See https://github.com/pyload/pyload/security/advisories/GHSA-ccxc-x975-4hh9 for patch details and verification instructions.
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.
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
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
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing
Same weakness CWE-295 – Improper Certificate Validation
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-29120
GHSA-ccxc-x975-4hh9