| Advisory ID | pypa/pyload-ng/PYSEC-2026-2998 |
| Aliases |
CVE-2026-45306
GHSA-w727-595x-pc3r PYSEC-2026-2998 |
| Summary | pyLoad Has Incomplete Fix for CVE-2026-33509 -storage_folder Bypass via Session Directory in pyLoad ## Summary The fix for CVE-2026-33509 prevents setting `storage_folder` inside `PKGDIR` or `userdir`, but does NOT protect the Flask session directory (`/tmp/pyLoad/flask`). An authenticated attacker can set `storage_folder` to the session directory and download session files of other users via `/files/get/`, leading to account takeover. ## Details The fix in `src/pyload/core/api/__init__.py`: ```python directories = [PKGDIR, userdir] if any(directories[0].startswith(d) for d in directories[1:]): return # blocked ``` But the Flask session directory is: ```python session_storage_path = os.path.join(api.get_cachedir(), "flask") # = /tmp/pyLoad/flask ← NOT blocked by fix ``` ## Attack Chain 1. Attacker (admin) sets `storage_folder = /tmp/pyLoad/flask` 2. Fix does NOT block this — `/tmp/pyLoad/flask` not inside `PKGDIR` or `userdir` 3. Attacker requests `GET /files/get/<victim_session_filename>` 4. `send_from_directory('/tmp/pyLoad/flask', session_file)` serves victim's session 5. Attacker uses stolen session → **Account Takeover** ## PoC <img width="592" height="408" alt="POC" src="https://github.com/user-attachments/assets/936b9f56-325b-437d-9edd-e0d5bb995187" /> ```python import os PKGDIR = "/usr/lib/python3/dist-packages/pyload" userdir = os.path.expanduser("~/.pyload") session_dir = "/tmp/pyLoad/flask" correct_case = lambda x: x directories = [ correct_case(os.path.join(os.path.realpath(d), "")) for d in [session_dir, PKGDIR, userdir] ] blocked = any(directories[0].startswith(d) for d in directories[1:]) print(f"Fix blocks session_dir: {blocked}") # Output: Fix blocks session_dir: False ← BYPASS CONFIRMED ``` ## Impact Authenticated admin can steal sessions of other users → Account Takeover. ## Suggested Fix ```python blocked_dirs = [PKGDIR, userdir, api.get_cachedir()] directories = [ os.path.join(os.path.realpath(d), "") for d in [value] + blocked_dirs ] if any(directories[0].startswith(d) for d in directories[1:]): return ``` |
| Status | Published |
| Exploitability | 0.5 |
| Weighted Severity | 5.9 |
| Risk | 3.0 |
| Affected and Fixed Packages | Package Details |
| Introduced and Fixed Package Commit Patches | Package Commit Patches Details |
| There are no known CWE. |
| System | Score | Found at |
|---|---|---|
| cvssv3.1 | 6.5 | https://github.com/pypa/advisory-database/blob/main/vulns/pyload-ng/PYSEC-2026-2998.yaml |
| Reference id | Reference type | URL |
|---|---|---|
| https://github.com/pyload/pyload | ||
| https://github.com/pyload/pyload/security/advisories/GHSA-w727-595x-pc3r | ||
| https://pypi.org/project/pyload-ng | ||
| CVE-2026-45306 | https://nvd.nist.gov/vuln/detail/CVE-2026-45306 | |
| GHSA-r7mc-x6x7-cqxx | https://github.com/advisories/GHSA-r7mc-x6x7-cqxx | |
| GHSA-w727-595x-pc3r | https://github.com/advisories/GHSA-w727-595x-pc3r |
No EPSS data available for this advisory.
| Patch URL | |
|---|---|
| There are no known patches. | |
| Attack Vector (AV) | Attack Complexity (AC) | Privileges Required (PR) | User Interaction (UI) | Scope (S) | Confidentiality Impact (C) | Integrity Impact (I) | Availability Impact (A) |
|---|---|---|---|---|---|---|---|
network adjacent_network local physical |
low high |
none low high |
none required |
unchanged changed |
high low none |
high low none |
high low none |
Vector: SSVCv2/E:P/A:N/T:P/P:M/B:A/M:M/D:T/2026-05-28T18:49:27Z/
Decision: Track
Source URL: https://github.com/cisagov/vulnrichment/blob/develop/2026/45xxx/CVE-2026-45306.json
Source Advisory: vulnrichment/CVE-2026-45306
[{'Exploitation': 'poc'},
{'Automatable': 'no'},
{'Technical Impact': 'partial'},
{'Mission Prevalence': 'minimal'},
{'Public Well-being Impact': 'material'},
{'Mission & Well-being': 'medium'}]