pyload-ng CVE-2026-44226
MEDIUMSeverity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
Lifecycle Timeline
2DescriptionGitHub Advisory
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:
- Unauthenticated template-render route:
src/pyload/webui/app/blueprints/app_blueprint.py:32-36@bp.route("/web/<path:filename>", endpoint="web")data = render_template(filename)with user-controlledfilename- no
@login_required(...)on this route
- Global exception handler exposes traceback to response:
src/pyload/webui/app/handlers.py:14-27tb = traceback.format_exc()messages.extend(tb.split('\n'))- returned in rendered error page for all exceptions
- Error page renders all
messages:
src/pyload/webui/app/themes/modern/templates/base.html:217-219- loops over
messagesand 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
#!/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 read_text(rel: str) -> str:
return (ROOT / rel).read_text(encoding="utf-8")
def route_has_no_login_required(app_blueprint: 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)",
app_blueprint,
re.DOTALL,
)
if not m:
return False
block_start = max(0, m.start() - 200)
block = app_blueprint[block_start:m.end()]
return "@login_required(" not in block
def main() -> None:
workdir = Path(tempfile.mkdtemp(prefix="pyload-traceback-infoleak-"))
try:
app_blueprint = read_text("webui/app/blueprints/app_blueprint.py")
handlers = read_text("webui/app/handlers.py")
base_template = read_text("webui/app/themes/modern/templates/base.html")
unauth_web_route = '/web/<path:filename>' in app_blueprint and route_has_no_login_required(app_blueprint)
user_controlled_template_name = "render_template(filename)" in app_blueprint
handler_uses_traceback = "traceback.format_exc()" in handlers
handler_appends_trace = "messages.extend(tb.split('\\n'))" in handlers
global_exception_handler = "(Exception, handle_exception_error)" in handlers
template_renders_messages = "{% for message in messages %}" in base_template and "{{message}}" in base_template
leaked_traceback_keyword = False
leaked_exception_type = False
try:
raise RuntimeError("forced-poc-error")
except Exception:
tb = traceback.format_exc()
messages = [f"Error 500: forced-poc-error"]
messages.extend(tb.split("\\n"))
joined = "\\n".join(messages)
leaked_traceback_keyword = "Traceback (most recent call last)" in joined
leaked_exception_type = "RuntimeError: forced-poc-error" in joined
repro_success = all(
[
unauth_web_route,
user_controlled_template_name,
handler_uses_traceback,
handler_appends_trace,
global_exception_handler,
template_renders_messages,
leaked_traceback_keyword,
leaked_exception_type,
]
)
print("unauth_web_route=", unauth_web_route)
print("user_controlled_template_name=", user_controlled_template_name)
print("handler_uses_traceback=", handler_uses_traceback)
print("handler_appends_trace=", handler_appends_trace)
print("global_exception_handler=", global_exception_handler)
print("template_renders_messages=", template_renders_messages)
print("leaked_traceback_keyword=", leaked_traceback_keyword)
print("leaked_exception_type=", leaked_exception_type)
print("traceback_infoleak_repro_success=", repro_success)
finally:
shutil.rmtree(workdir, ignore_errors=True)
print("cleanup_done=True")
if __name__ == "__main__":
main()Observed result:
unauth_web_route= True
user_controlled_template_name= True
handler_uses_traceback= True
handler_appends_trace= True
global_exception_handler= True
template_renders_messages= True
leaked_traceback_keyword= True
leaked_exception_type= True
traceback_infoleak_repro_success= True
cleanup_done=TrueImpact
- 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.
AnalysisAI
PyLoad-ng WebUI discloses internal Python stack traces and source file paths to unauthenticated remote attackers via a global exception handler on the /web/<path:filename> endpoint. An attacker can request non-existent templates or craft malformed requests to trigger server exceptions and extract implementation details in HTTP responses without authentication. This information disclosure facilitates reconnaissance for follow-on attacks but does not enable direct code execution or data theft.
Technical ContextAI
PyLoad-ng is a Python-based download manager with a Flask-based WebUI. The vulnerability stems from three interconnected flaws in the Flask application architecture: the /web/<path:filename> route (app_blueprint.py:32-36) accepts user-controlled template filenames via render_template(filename) without authentication decorators; the global exception handler (handlers.py:14-27) uses traceback.format_exc() and appends the full traceback to the messages list; and the Jinja2 template base.html:217-219 renders all messages in the response HTML without sanitization. When Flask encounters an unhandled exception (e.g., FileNotFoundError for a non-existent template), the exception handler captures the complete call stack including module paths, function names, variable states, and exception metadata, then passes this to the template renderer where it is output directly to the HTTP response body.
RemediationAI
Upgrade pyload-ng to version 0.5.0b3.dev100 or later, which includes fixes to remove the global exception handler's traceback exposure and add authentication to the /web/<path:filename> route. Apply the patch via pip install --upgrade pyload-ng>=0.5.0b3.dev100. If immediate upgrade is not possible, implement the following compensating controls: add @login_required decorator to the /web/<path:filename> route in app_blueprint.py to require authentication before template rendering; modify the global exception handler in handlers.py to log tracebacks server-side only (via logging.error) and return a generic error message to clients without stack details; set Flask's PROPAGATE_EXCEPTIONS=False and DEBUG=False in production to prevent debug pages from leaking implementation details. These controls mitigate the immediate disclosure risk but do not address the underlying design issue; apply the vendor patch as soon as feasible.
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-209 – Error Message Information Leak
View allSame technique Information Disclosure
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-c3gc-9pf2-84gg