Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessReach pyLoad WebUI unauthenticated
-
ExploitRequest /web/<filename>.html template route
-
ExecutionRender protected templates or trigger 500 errors
-
ImpactHarvest internal variable names and enumerate templates
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A10:2025 - Mishandling of Exceptional Conditions
ASVS 5.0
V16 - Security Logging and Error Handling Error message sanitization
MITRE ATT&CK
1 technique across 1 tactic: Discovery The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | No special configuration is required: the /web/<path:filename> route in app_blueprint.py has no @login_required decorator, so remote unauthenticated exploitation works against default installs of pyLoad (pyload-ng <= 0.5.0b3.dev100) wherever the WebUI is network-reachable (default port 8000). The only prerequisite is HTTP reachability of the WebUI. Limiting factors on real-world impact: the exposure is confined to template rendering, internal Jinja2 variable-name leakage via HTTP 500 bodies, and template-name enumeration - info.html's sensitive values (Python version, OS platform, install/config folders, port) are populated client-side via JavaScript, so only field labels and structure are leaked server-side; there is no authentication bypass into actual download/queue data content and no write or code-execution capability. |
| Impact | This is a genuine access-control bypass (CWE-209 / information disclosure) but a low-to-moderate real-world priority, consistent with its CVSS 3.1 base score of 5.3. The CVSS vector (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) confirms remote, low-complexity, unauthenticated exploitation with only limited confidentiality impact and no integrity or availability impact - matching the description, which shows disclosure of template structure, field labels, internal Jinja2 variable names, and template enumeration rather than code execution or credential theft. No EPSS score, CISA KEV listing, or SSVC decision data was provided, so exploitation probability and automatability cannot be quantified from the input; absence of KEV means there is no evidence of active exploitation. A functional proof-of-concept (curl-based) is published directly in the GHSA advisory, so working exploit code is public even though no separate POC flag was supplied. The signals are internally consistent - there is no network-vs-local conflict and no severity contradiction - but note the disclosed data is largely structural: info.html field values are populated client-side via JavaScript, so the server-side leak is mainly field labels and internal variable names, which tempers the practical confidentiality impact below what 'unauthenticated template access' might first suggest. The authors themselves flag the forward-looking risk: any future template rendering sensitive data server-side would be immediately exposed through this route. |
| Exploit ScenarioDerived | An attacker who can reach the pyLoad WebUI (default port 8000) sends unauthenticated HTTP GET requests to /web/<template>.html, rendering pages like logs.html, info.html, and dashboard.html that are otherwise protected by @login_required on their direct routes. By requesting templates that fail to render (e.g. settings.html), the attacker reads HTTP 500 bodies leaking internal Jinja2 variable names such as "'conf' is undefined" and enumerates valid template filenames via 200-vs-500 response differentiation. A public curl-based PoC for all of these steps is included in the GHSA advisory. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 09, 2026
Unauthenticated remote requests to pyLoad's /web/<path:filename> route render Jinja2 page templates that are otherwise gated behind @login_required on their direct routes (/logs, /settings, /queue, /dashboard), and a typo in the exception handler (exc.desc instead of exc.description) causes internal Jinja2 variable names such as "'conf' is undefined" to be echoed in HTTP 500 response bodies. The behavior affects pyLoad (pyload-ng) up to and including 0.5.0b3.dev100 on default installs with the WebUI reachable on port 8000 (CVSS 3.1 base 5.3, AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N); per the CVSS vector, no authentication is required. Impact is confined to template rendering, information disclosure and template-name enumeration (200 vs 500 differentiation) - no download/queue data exfiltration, write, or code execution - and the upstream GHSA ships step-by-step curl reproduction commands, though no public weaponized exploit is referenced in the supplied data. Note that info.html's sensitive values (Python version, OS platform, install/config folders, port) are populated client-side via JavaScript, so server-side leakage is largely limited to field labels and structure.
RemediationAI
Vendor-released patch: upgrade pyLoad (pyload-ng) to 0.5.0b3.dev101 or later via pip; the fix commit e80c940cd604e60d93e3164429d4fc4aac54468d (https://github.com/pyload/pyload/commit/e80c940cd604e60d93e3164429d4fc4aac54468d) adds an authentication gate to the template route that redirects unauthenticated callers to the login page while still permitting login.html, and replaces the exception handler's leaky f-string with a generic "Error: exception occurred while processing the request" message (side effect: less verbose error output for legitimate administrators, which should be captured in logs instead). If immediate upgrading is not possible, compensating controls are: bind the WebUI to localhost or a management-only network segment (and reach it over an SSH tunnel or VPN) rather than exposing port 8000, which removes remote reachability entirely at the cost of convenience; or front the service with a reverse proxy that rejects or returns 404 for any request whose path matches /web/ while allowing /login and the legitimate top-level routes, trading a small amount of configuration complexity for blocking the vulnerable endpoint; alternatively restrict /web/* by source IP allowlist. Generic network ACLs on port 8000 should be verified as these also blunt the information-disclosure path. Consult the vendor advisory GHSA-j92p-c242-7hfx for the authoritative fix details before deploying any workaround.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 2 packages in pypi, euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
pyLoad's WebUI is a Flask application whose routes live in src/pyload/webui/app/blueprints/app_blueprint.py. Sensitive routes such as /logs, /settings and /files each carry a @login_required(...) decorator, but the generic template-serving route @bp.route("/web/<path:filename>", endpoint="web") was left undecorated: it guesses a MIME type and calls render_template(filename) directly, passing the user-controlled path segment straight into Jinja2's template loader. Because the same loader resolves every other page template, the authentication model enforced at the route layer is bypassed at the template layer. The second defect is in src/pyload/webui/app/handlers.py, where handle_exception_error() reads a non-existent attribute exc.desc; the mandatory AttributeError branch assigns the raw exception object to desc and interpolates it into the response message (f"Error {code}: {desc}"), so str(exc) - including UndefinedError text or TemplateNotFound filenames - is written into the HTML body returned to unauthenticated callers. The CVE is classified CWE-209 (Generation of Error Message Containing Sensitive Information), with the missing access-control check exacerbating the information exposure; the affected package is pkg:pip/pyload-ng.
Know when Python gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
Route is remotely reachable with no auth and no user interaction (AV:N/AC:L/PR:N/UI:N); only limited structural/variable-name disclosure (C:L), no integrity or availability impact.
Primary rating from Vendor (https://github.com/pyload/pyload).
CVSS VectorVendor: https://github.com/pyload/pyload
DescriptionCVE.org
Summary
The /web/<path:filename> route in src/pyload/webui/app/blueprints/app_blueprint.py renders Jinja2 templates without any authentication requirement. Every equivalent direct route (/logs, /settings, /queue, /dashboard, etc.) is protected by @login_required, but the underlying templates for all of these pages are accessible unauthenticated via this endpoint. Combined with an exception attribute typo in src/pyload/webui/app/handlers.py (exc.desc instead of exc.description), internal Jinja2 variable names are leaked in HTTP 500 response bodies to unauthenticated callers. An attacker can also enumerate all valid template names by observing 200 vs 500 response differentiation.
Details
Bug 1 - Missing authentication on /web/<path:filename>
File: src/pyload/webui/app/blueprints/app_blueprint.py, lines 32-36
@bp.route("/web/<path:filename>", endpoint="web")
def render(filename):
# ← no @login_required
mimetype = mimetypes.guess_type(filename)[0] or "text/html"
data = render_template(filename)
return flask.Response(data, mimetype=mimetype)Every other sensitive route in the same file is protected:
@bp.route("/logs", ...)
@login_required("LIST")
# protected
@bp.route("/settings", ...)
@login_required("SETTINGS")
# protected
@bp.route("/files", ...)
@login_required("DOWNLOAD")
# protectedThe /web/<path:filename> route has no such decorator, allowing any unauthenticated HTTP client to render arbitrary templates by supplying their filename in the URL path.
Bug 2 - Exception attribute typo causes internal details in error responses
File: src/pyload/webui/app/handlers.py, lines 12-20
def handle_exception_error(exc):
try:
code = exc.code
desc = exc.desc
# BUG: attribute does not exist on standard exceptions
except AttributeError:
# always raised - falls here for every exception
code = 500
desc = exc
# raw exception object assigned to desc
message = f"Error {code}: {desc}"
# str(exc) embedded in response body
return render_template("error.html", messages=[message]), codeexc.desc does not exist on standard Python or Jinja2 exceptions. The AttributeError branch is always taken for template rendering failures. desc is set to the raw exception object, and str(exc) is embedded in the HTML response body returned to the unauthenticated caller. For a UndefinedError this produces 'conf' is undefined. For TemplateNotFound it produces the template filename.
PoC
Tested against pyload-ng develop branch (0.5.0b3.dev), default install, no authentication cookies or credentials used in any request.
Test 1 - Unauthenticated page render confirmed (HTTP 200)
curl -si http://TARGET:8000/web/logs.html | grep "HTTP\|title"
Test 2 - System info page with sensitive field labels rendered unauthenticated
html
<dt><b>Python Version:</b></dt>
<dt><b>OS Platform:</b></dt>
<dt><b>Installation Folder:</b></dt>
<dt><b>Config Folder:</b></dt>```
Test 3 - Internal Jinja2 variable name leaked in HTTP 500 body (unauthenticated)HTTP/1.1 500 INTERNAL SERVER ERROR <p><b>Error 500: 'conf' is undefined</b></p>` Test 4 - Template enumeration via response code differentiation
curl -o /dev/null -sw "%{http_code}\n" http://TARGET:8000/web/info.html
curl -o /dev/null -sw "%{http_code}\n" http://TARGET:8000/web/dashboard.html
curl -o /dev/null -sw "%{http_code}\n" http://TARGET:8000/web/settings.html
curl -o /dev/null -sw "%{http_code}\n" http://TARGET:8000/web/queue.html
curl -o /dev/null -sw "%{http_code}\n" http://TARGET:8000/web/collector.html
curl -o /dev/null -sw "%{http_code}\n" http://TARGET:8000/web/filemanager.html
curl -o /dev/null -sw "%{http_code}\n" http://TARGET:8000/web/nonexistent_xyz.html
200 ← logs.html (exists, renders without auth)
200 ← info.html (exists, renders without auth)
200 ← dashboard.html (exists, renders without auth)
500 ← settings.html (exists, missing auth context - leaks 'conf' is undefined)
500 ← queue.html (exists, missing auth context)
500 ← collector.html (exists, missing auth context)
500 ← filemanager.html (exists, missing auth context)
500 ← nonexistent_xyz (does not exist - same 500, no differentiation on miss)```
###Impact
An unauthenticated remote attacker can:
Render application page templates without any credentials, bypassing the access control model enforced on all direct routes
Access the system information page (info.html) exposing field structure for Python version, OS platform, pyLoad version, installation folder, config folder, and WebUI port - values are populated via JS but field labels confirm application structure
Access the full log viewer UI (logs.html) and download dashboard (dashboard.html) without authentication
Extract internal Jinja2 template variable names from HTTP 500 response bodies ('conf' is undefined, etc.)
Enumerate all valid template filenames by observing 200 vs 500 response codes
The access control inconsistency is the core issue: the authentication model enforced on direct routes is completely bypassed via the /web/<path:filename> endpoint. Any future template that renders sensitive data server-side would be immediately exposed to unauthenticated access through this route.Blast Radius
ecosystem impact- 1 pypi packages depend on pyload-ng (1 direct, 0 indirect)
Ecosystem-wide dependent count for version 0.5.0b3.dev101.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.
Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.
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.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
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
EUVD-2026-95911
GHSA-j92p-c242-7hfx
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB