CVE-2026-44226: pyLoad: Unauthenticated traceback disclosure via global exception handler in WebUI
Summary pyload-ng WebUI returns full Python traceback details to clients on unhandled exceptions.
Because /web/<path:filename> is reachable without authentication and renders attacker-controlled template names, an unauthenticated user can reliably trigger a server exception (for example by requesting a non-existent template) and receive internal stack traces in the HTTP response.
Details The issue is caused by the combination of:
1. Unauthenticated template-render route: - src/pyload/webui/app/blueprints/appblueprint.py:32-36 - @bp.route("/web/<path:filename>", endpoint="web") - data = rendertemplate(filename) with user-controlled filename - no @loginrequired(...) on this route
2. Global exception handler exposes traceback to response: - src/pyload/webui/app/handlers.py:14-27 - tb = traceback.formatexc() - messages.extend(tb.split('\n')) - returned in rendered error page for all exceptions
3. Error page renders all messages: - src/pyload/webui/app/themes/modern/templates/base.html:217-219 - loops over messages and prints them in response HTML
So any unhandled exception can disclose internal implementation details (stack frames, source paths, exception metadata) to remote unauthenticated clients.
This is a core behavior issue in default WebUI error handling
PoC python #!/usr/bin/env python3 from future import annotations
import re import shutil import tempfile import traceback from pathlib import Path
ROOT = Path(file).resolve().parent / "pyload" / "src" / "pyload"
def readtext(rel: str) -> str: return (ROOT / rel).readtext(encoding="utf-8")
def routehasnologinrequired(appblueprint: str) -> bool: m = re.search( r'@bp\\.route\\("/web/<path:filename>", endpoint="web"\\)\\s' r"def render\\(filename\\):(?P<body>.?)(?:\\n\\n@bp\\.route|\\Z)", appblueprint, re.DOTALL, ) if not m: return False blockstart = max(0, m.start() - 200) block = appblueprint[blockstart:m.end()] return "@loginrequired(" not in block
def main() -> None: workdir = Path(tempfile.mkdtemp(prefix="pyload-traceback-infoleak-")) try: appblueprint = readtext("webui/app/blueprints/appblueprint.py") handlers = readtext("webui/app/handlers.py") basetemplate = readtext("webui/app/themes/modern/templates/base.html")
unauthwebroute = '/web/<path:filename>' in appblueprint and routehasnologinrequired(appblueprint) usercontrolledtemplatename = "rendertemplate(filename)" in appblueprint handlerusestraceback = "traceback.formatexc()" in handlers handlerappendstrace = "messages.extend(tb.split('\\n'))" in handlers globalexceptionhandler = "(Exception, handleexceptionerror)" in handlers templaterendersmessages = "{% for message in messages %}" in basetemplate and "{{message}}" in basetemplate
leakedtracebackkeyword = False leakedexceptiontype = False try: raise RuntimeError("forced-poc-error") except Exception: tb = traceback.formatexc() messages = [f"Error 500: forced-poc-error"] messages.extend(tb.split("\\n")) joined = "\\n".join(messages) leakedtracebackkeyword = "Traceback (most recent call last)" in joined leakedexceptiontype = "RuntimeError: forced-poc-error" in joined
reprosuccess = all( [ unauthwebroute, usercontrolledtemplatename, handlerusestraceback, handlerappendstrace, globalexceptionhandler, templaterendersmessages, leakedtracebackkeyword, leakedexceptiontype, ] )
print("unauthwebroute=", unauthwebroute) print("usercontrolledtemplatename=", usercontrolledtemplatename) print("handlerusestraceback=", handlerusestraceback) print("handlerappendstrace=", handlerappendstrace) print("globalexceptionhandler=", globalexceptionhandler) print("templaterendersmessages=", templaterendersmessages) print("leakedtracebackkeyword=", leakedtracebackkeyword) print("leakedexceptiontype=", leakedexceptiontype) print("tracebackinfoleakreprosuccess=", reprosuccess) finally: shutil.rmtree(workdir, ignoreerrors=True) print("cleanupdone=True")
if name == "main": main()
Observed result: text unauthwebroute= True usercontrolledtemplatename= True handlerusestraceback= True handlerappendstrace= True globalexceptionhandler= True templaterendersmessages= True leakedtracebackkeyword= True leakedexceptiontype= True tracebackinfoleakreprosuccess= True cleanupdone=True
Impact - Vulnerability type: Information disclosure (stack trace / internal path leakage). - Attack surface: unauthenticated WebUI request path. - Exposes internal error details that help attackers map application internals and improve exploit reliability for follow-on attacks.
Other sources
pyLoad is a free and open-source download manager written in Python. Prior to 0.5.0b3.dev100, pyload-ng WebUI returns full Python traceback details to clients on unhandled exceptions. Because /web/<path:filename> is reachable without authentication and renders attacker-controlled template names, an unauthenticated user can reliably trigger a server exception (for example by requesting a non-existent template) and receive internal stack traces in the HTTP response. This vulnerability is fixed in 0.5.0b3.dev100.
— MITRE
Affected Software
Event History
Frequently Asked Questions
What is the severity of CVE-2026-44226?
CVE-2026-44226 has been evaluated as having a medium severity due to the potential exposure of sensitive information through full traceback details.
How do I fix CVE-2026-44226?
To mitigate CVE-2026-44226, upgrade pyload-ng to version 0.5.0b3.dev100 or later, which addresses this vulnerability.
What is the impact of CVE-2026-44226?
The impact of CVE-2026-44226 includes the possibility for an unauthenticated attacker to trigger server exceptions and access sensitive debugging information.
Who is affected by CVE-2026-44226?
CVE-2026-44226 affects all installations of pyload-ng versions prior to 0.5.0b3.dev100.
Is CVE-2026-44226 an authentication bypass vulnerability?
CVE-2026-44226 is not an authentication bypass vulnerability, but it allows unauthenticated users to exploit server exceptions.