Loading...
Skip to main content

CVE-2024-32880

CRITICAL

pyLoad allows upload to arbitrary folder lead to RCE

Published June 29, 2026Updated July 9, 2026Source: osv

Summary

### Summary An authenticated user can change the download folder and upload a crafted template to the specified folder lead to remote code execution ### Details example version: 0.5 file:src/pyload/webui/app/blueprints/app_blueprint.py ```python @bp.route("/render/<path:filename>", endpoint="render") def render(filename): mimetype = mimetypes.guess_type(filename)[0] or "text/html" data = render_template(filename) return flask.Response(data, mimetype=mimetype) ``` So, if we can control file in the path "pyload/webui/app/templates" in latest version and path in "module/web/media/js"(the difference is the older version0.4.20 only renders file with extension name ".js"), the render_template func will works like SSTI(server-side template injection) when render the evil file we control. in /settings page and the choose option general/general, where we can change the download folder. ![image](https://github.com/pyload/pyload/assets/48705773/0b239138-9aaa-45c4-bf84-c1c3103c452a) Also, we can find the pyLoad install folder in /info page ![image](https://github.com/pyload/pyload/assets/48705773/6e9d363a-f0e0-4d25-92b3-b1587188a235) So, we can change the value of Download folder to the template path. Then through /json/add_package we can upload a crafted template file to RCE. ```python @bp.route("/json/add_package", methods=["POST"], endpoint="add_package") # @apiver_check @login_required("ADD") def add_package(): api = flask.current_app.config["PYLOAD_API"] package_name = flask.request.form.get("add_name", "New Package").strip() queue = int(flask.request.form["add_dest"]) links = [l.strip() for l in flask.request.form["add_links"].splitlines()] pw = flask.request.form.get("add_password", "").strip("\n\r") try: file = flask.request.files["add_file"] if file.filename: if not package_name or package_name == "New Package": package_name = file.filename file_path = os.path.join( api.get_config_value("general", "storage_folder"), "tmp_" + file.filename ) file.save(file_path) links.insert(0, file_path) except Exception: pass urls = [url for url in links if url.strip()] pack = api.add_package(package_name, urls, queue) if pw: data = {"password": pw} api.set_package_data(pack, data) return jsonify(True) ``` ### PoC First login into the admin page, then visit the info page to get the path of pyload installation folder. Second, change the download folder to PYLOAD_INSTALL_DIR/ webui/app/templates/ Third, upload crafted template file through /json/add_package through parameter add_file the content of crafted template file and its filename is "341.html": ``` {{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}} ``` ![image](https://github.com/pyload/pyload/assets/48705773/a933a95b-bb18-4e2e-a442-973585e7d1fc) Last, visit http://TARGET/render/tmp_341.html to trigger the RCE ![image](https://github.com/pyload/pyload/assets/48705773/80a1ba00-2774-4ce5-bc9e-dd32f189634e) ![image](https://github.com/pyload/pyload/assets/48705773/136236f2-9b00-4506-a8ac-29a14a537bbe) ### Impact It is a RCE vulnerability and I think it affects all versions. In earlier version 0.4.20, the trigger difference is the pyload installation folder path difference and the upload file must with extension ".js" . The render js code in version 0.4.20: ```python @route("/media/js/<path:re:.+\.js>") def js_dynamic(path): response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(time.time() + 60 * 60 * 24 * 2)) response.headers['Cache-control'] = "public" response.headers['Content-Type'] = "text/javascript; charset=UTF-8" try: # static files are not rendered if "static" not in path and "mootools" not in path: t = env.get_template("js/%s" % path) return t.render() else: return static_file(path, root=join(PROJECT_DIR, "media", "js")) except: return HTTPError(404, "Not Found") ```

Affected Packages (1)

PackageEcosystemAffectedFixed In
pyload-ng
pypi
0.5.0a5.dev528, 0.5.0a5.dev532, 0.5.0a5.dev535, 0.5.0a5.dev536 (+102 more)Range-based data available

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.1 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
High
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H

Frequently Asked Questions

What is CVE-2024-32880?
pyLoad allows upload to arbitrary folder lead to RCE This vulnerability has been assigned a severity rating of CRITICAL (CVSS score: 9.1/10).
How do I check if my project is affected by CVE-2024-32880?
CVE-2024-32880 affects pyload-ng. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2024-32880 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.1

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

PYSEC-2026-492
GHSA-3f7w-p8vr-4v5f

Related CVEs

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies