CVE-2026-75597 Overview
pyLoad, a free and open-source download manager written in Python, contains an information disclosure vulnerability in versions prior to 0.5.0b3.dev101. The /web/<path:filename> route in src/pyload/webui/app/blueprints/app_blueprint.py renders Jinja2 templates without enforcing authentication. While equivalent direct routes such as /logs, /settings, /queue, and /dashboard require @login_required, the underlying templates remain reachable through the unauthenticated endpoint. A separate exception attribute typo in src/pyload/webui/app/handlers.py leaks internal Jinja2 variable names in HTTP 500 responses. The issue is tracked under [CWE-209: Generation of Error Message Containing Sensitive Information].
Critical Impact
Unauthenticated remote attackers can access protected UI templates, enumerate valid template names via 200/500 response differentiation, and extract internal Jinja2 variable names from verbose error messages.
Affected Products
- pyLoad download manager
- All versions prior to 0.5.0b3.dev101
- Deployments exposing the pyLoad web UI to untrusted networks
Discovery Timeline
- 2026-10-09 - CVE CVE-2026-75597 published to NVD
- 2026-10-09 - Last updated in NVD database
Technical Details for CVE-2026-75597
Vulnerability Analysis
The vulnerability combines two defects. First, the /web/<path:filename> Flask route in app_blueprint.py renders arbitrary Jinja2 templates through render_template(filename) without checking the caller's session. Every protected page in the application (such as /logs, /settings, /queue, /dashboard) has an equivalent template file reachable through this route, bypassing the @login_required decorator applied to the canonical URLs.
Second, handle_exception_error in handlers.py references exc.desc instead of the correct Werkzeug attribute exc.description. The resulting AttributeError is caught and the raw exception object is formatted into the user-facing error page, which exposes Jinja2 internal variable names and template context details to unauthenticated callers.
Root Cause
The root cause is missing authorization on a template-rendering endpoint combined with verbose error handling. The developer applied access control at the route layer for named endpoints but left the generic template-serving route open. The attribute typo turned a controlled 500 response into an uncontrolled information leak.
Attack Vector
An unauthenticated attacker sends HTTP GET requests to /web/<template_name> and observes response codes. A 200 response confirms a valid template and returns its rendered output. A 500 response confirms a template exists but references undefined context variables, with the error body disclosing those variable names. This allows template enumeration and structural reconnaissance of the application without credentials.
# Patch applied to src/pyload/webui/app/blueprints/app_blueprint.py
@bp.route("/web/<path:filename>", endpoint="web")
def render(filename):
# Allow login.html without authentication, protect all other files
if filename != "login.html" and not is_authenticated():
location = flask.url_for("app.login", next="index")
return flask.redirect(location)
mimetype = mimetypes.guess_type(filename)[0] or "text/html"
data = render_template(filename)
return flask.Response(data, mimetype=mimetype)
Source: GitHub Commit e80c940
Detection Methods for CVE-2026-75597
Indicators of Compromise
- Unauthenticated HTTP GET requests to /web/ paths referencing template names such as logs.html, settings.html, queue.html, or dashboard.html.
- Bursts of requests to /web/<filename> from a single source yielding mixed 200 and 500 responses, indicative of template enumeration.
- HTTP 500 response bodies originating from pyLoad that contain Jinja2 variable identifiers or UndefinedError strings.
Detection Strategies
- Review web server and reverse proxy logs for access to /web/* paths without a preceding authenticated session cookie.
- Alert on anomalous volumes of 500 responses from the pyLoad web UI, which correlate with template name probing.
- Compare source IPs issuing /web/ requests against the set of IPs that completed /login within the same session window.
Monitoring Recommendations
- Forward pyLoad access and error logs to a centralized log platform for retention and correlation.
- Baseline normal /web/ traffic patterns and flag deviations in request rate or response code distribution.
- Monitor for outbound disclosure of error pages containing Jinja2 context data in web application firewall logs.
How to Mitigate CVE-2026-75597
Immediate Actions Required
- Upgrade pyLoad to version 0.5.0b3.dev101 or later, which contains the official patch.
- Restrict network exposure of the pyLoad web UI to trusted administrative networks or a VPN until patching is complete.
- Audit recent access logs for unauthenticated /web/<filename> requests and investigate any confirmed template reads.
Patch Information
The fix is committed in GitHub Commit e80c940 and documented in GitHub Security Advisory GHSA-j92p-c242-7hfx. The patch adds an is_authenticated() check to the /web/<path:filename> route, allowing only login.html without a session. The error handler is simplified to return a generic message, eliminating the attribute lookup that leaked internal context.
Workarounds
- Place pyLoad behind a reverse proxy that requires authentication for all /web/ paths except /web/login.html.
- Block external access to /web/* at the network edge until the upgrade is applied.
- Configure the reverse proxy to strip or replace HTTP 500 response bodies originating from pyLoad to prevent error-based information disclosure.
# Example nginx snippet to require authentication on /web/ paths except login.html
location ~ ^/web/(?!login\.html$).+ {
auth_request /auth;
proxy_pass http://127.0.0.1:8000;
}
location = /web/login.html {
proxy_pass http://127.0.0.1:8000;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

