Skip to main content
Vulnerability Database/CVE-2026-75597

CVE-2026-75597: pyLoad Information Disclosure Vulnerability

CVE-2026-75597 is an information disclosure flaw in pyLoad that exposes Jinja2 templates without authentication, allowing attackers to leak internal variable names and enumerate template paths. This post covers technical details, affected versions, impact assessment, and mitigation strategies.

Published:

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.

python
# 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.
bash
# 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.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.