pyload-ng: getUserData/get_userdata exposed at Perms.ANY allow any authenticated account to brute-force the administrator password
## Summary
`Api.getUserData` (legacy) and `Api.get_userdata` are declared with `@permission(Perms.ANY)` and are reachable at `/api/getUserData` and `/api/get_userdata`. Because `Perms.ANY == 0` and pyLoad's permission check is a bitmask AND, that gate is a no-op: **every authenticated account passes, including one holding zero permission bits.**
Both methods are thin wrappers around `check_auth()`, which the maintainers deliberately restricted to administrators by omitting `@permission` (no entry in `perm_map`, so `is_authorized()` returns `False` for non-admins). The wrappers undo that protection.
An attacker holding the lowest-privileged
pyLoad: Rate-Limit Bypass and Audit-Log Spoofing via Trusted Client-Controlled `X-Forwarded-For` Header
## Summary
pyLoad determines the "client IP" used for its rate-limiting decorator and for its
security/audit logging by reading the client-supplied `X-Forwarded-For` (XFF) HTTP header and
taking the leftmost value. No trusted-proxy configuration exists (the Cheroot WSGI server faces
clients directly, and there is no `ProxyFix` middleware). Because any client can freely set this
header, an attacker can (1) completely bypass rate limiting by rotating the header on each request,
and (2) forge the source IP recorded in security logs for login and API-key authentication
failures, defeating IP-based blocking (e.g. fail2ban) and poisoning attributi
pyLoad: Privilege revocation and password change through the REST API do not invalidate the user's session
An admin who revokes a user's privileges through the REST API does not actually revoke them, because the session carrying those privileges is never invalidated.
pyLoad authorizes each request from values copied into the Flask session at login. set_session in webui/app/helpers.py writes role and perms once, and both login_required and the session branch of apikey_auth read them back from the session rather than from the database. The fix for GHSA-66hx-chf7-3332 handled this by deleting the user's session files, but the call was added only in webui/app/blueprints/json_blueprint.py, at the three WebUI form handlers. Api.set_user_permission and
pyLoad: Api.set_user_permission never invalidates the target's session
### Summary
An admin who revokes or downgrades a non-admin user's permissions through pyLoad's own documented
`/api/<func>` RPC surface — e.g. `POST /api/set_user_permission` (or its legacy alias
`/api/setUserPermission`) — updates the target's database row but never invalidates that user's
existing Flask cookie session. The demoted user keeps their pre-revocation `role`/`permission` bits
on every subsequent WebUI page load and every subsequent `/api/<func>` call made with that cookie,
for up to the default `session_lifetime` of ~31 days, or until they voluntarily log out. No action
by the demoted user is required beyond already being logged
pyLoad WindowsPhoneNotify addon: non-admin SETTINGS user triggers SSRF via unguarded http.client notification host
## Summary
pyLoad ships the WindowsPhoneNotify addon, whose `send()` method opens an HTTP connection to a host taken directly from the plugin's `pushurl` configuration value. A user holding the standard non-admin `SETTINGS` permission can set `pushurl` and `pushid` and enable the addon through the web API, since these plugin options are not in the admin-only option set. Once enabled, the addon activates dynamically without a restart, and any completed download (download events fire globally, not per user) causes the addon to send an HTTP POST to the configured host and path. The request is made with Python's `http.client.HTTPConnection`, so
pyLoad: Tar extraction creates device nodes and FIFOs (member types not filtered; tarfile extractall without filter=)
### Summary
`UnTar._safe_extractall` — the hardening added for GHSA-mvwx-582f-56r7 — validates member
**names** and symlink/hardlink **targets**, but never checks member **types**, and calls
`tarfile.extractall` without a `filter=`. On Python < 3.14 the default extraction filter is
`fully_trusted`, so a crafted tar containing device or FIFO entries makes pyLoad create
them on disk. When pyLoad runs as root (the official Docker deployment), a block-device
member grants raw disk access — full host compromise — reachable by any low-privileged user
who can trigger archive extraction (ADD to supply an archive, STATUS to invoke
`ExtractArchive.ext
pyLoad has an authentication bypass in API key validation (check_apikey cache)
## Summary
The API-key cache in `check_apikey()` allows an attacker to authenticate with a **forged API key** as long as the legitimate key for the same `key_id` has been used recently.
On a cache hit, the API key **secret is never verified**, resulting in a complete authentication bypass during the cache lifetime.
---
# Affected Components
- `src/pyload/core/api/init.py`
- `Api.check_apikey()`
- `src/pyload/core/database/apikey_database.py`
- `check_apikey()`
- `_check_key()`
The cache is used by normal API requests through:
- `src/pyload/webui/app/helpers.py`
which calls:
```python
api.check_apikey(api_key)
```
without prov
pyLoad: Unauthenticated access to /web/<path:filename> bypasses authentication on sensitive templates and leaks internal error details via exception attribute typo
pyLoad is a free and open-source download manager written in Python. Prior to 0.5.0b3.dev101, the `/web/<path:filename>` route in `src/pyload/webui/app/blueprints/app_blueprint.py` renders Jinja2 templates without any authentication requirement. Every equivalent direct route (`/logs`, `/settings`, `/queue`, `/dashboard`, etc.) is protected by `@login_required`, but the underlying templates for all of these pages are accessible unauthenticated via this endpoint. Combined with an exception attribute typo in `src/pyload/webui/app/handlers.py` (`exc.desc` instead of `exc.description`), internal Jinja2 variable names are leaked in HTTP 500 respons
Средний · CVSS 6.5EPSS 0,37%Публичный эксплойтЕсть исправление
pyLoad: Lack of Input Size Validation Leads to Denial of Service (DoS) and Process Termination
pyLoad is a free and open-source download manager written in Python. Prior to 0.5.0b3.dev101, the API `rpc` function in `api_blueprint.py` handles `multipart/form-data` uploads by reading the whole content of the uploaded file into memory with `file.read()`. This occurs before the data is sent to the underlying function. Since there is no size limit set at this point, a large file upload can exhaust the server's available memory which led to process termination. Version 0.5.0b3.dev101 contains a patch.
Strawberry GraphQL: Synchronous permission checks can treat an awaitable authorization result as truthy
Strawberry GraphQL is a library for creating GraphQL APIs. From 0.217.0 until 0.326.1, PermissionExtension.resolve() on a synchronous field resolver evaluates the result of has_permission() for truthiness. When a custom permission declares has_permission() as a normal function but returns an awaitable, supports_sync does not classify it as asynchronous, the awaitable is not awaited, and its inherently truthy object value permits the protected resolver to run even when the result would resolve to false. This affects synchronous field resolvers under both execute_sync() and execute(); permissions declared with async def has_permission() and syn
Strawberry GraphQL is a library for creating GraphQL APIs. From 0.312.3 until 0.327.2, the legacy graphql-ws subscription handler in strawberry/subscriptions/protocols/graphql_ws/handlers.py does not remove naturally completed operations from self.tasks and self.subscriptions. When max_subscriptions_per_connection is configured, a client on a persistent WebSocket connection can use distinct operation IDs for one-shot subscriptions to fill the connection's configured slots even after those subscriptions send complete, causing later legitimate operations on that connection to be rejected with Subscription limit reached. The modern graphql-trans
Banks: User-controlled prompt input can be parsed as privileged chat messages
Banks generates meaningful LLM prompts using a simple template language. Prior to 2.5.0, Banks Prompt.chat_messages() attempts to parse every line of rendered template output as ChatMessage JSON. When an application renders untrusted data and passes the returned ChatMessage objects to an LLM provider, attacker-controlled JSON can cross the prompt boundary and become a system, assistant, or tool message because ChatMessage.role accepts arbitrary strings. This can override application instructions, alter the intended prompt structure, or confuse downstream tool and message handling. This issue is fixed in version 2.5.0.
Banks: Symlink traversal and arbitrary file disclosure/overwrite in DirectoryPromptRegistry
Banks generates meaningful LLM prompts using a simple template language. Prior to 2.5.1, Banks DirectoryPromptRegistry does not reject symbolic links for index.json or discovered and existing .jinja prompt files. In an application where untrusted users can influence a prompt directory, DirectoryPromptRegistry._scan() and DirectoryPromptRegistry.get() can follow a link outside the registry root and disclose a file, while DirectoryPromptRegistry.set(), DirectoryPromptRegistry._save(), and DirectoryPromptRegistry._load() can read or overwrite an external link target. The issue requires attacker influence over the registry directory or its extrac
Indico is an event management system that uses Flask-Multipass, a multi-backend authentication system for Flask. Prior to 3.3.13, users who can create content, including speakers who can create minutes, can store crafted HTML in event minutes. When concurrent edits are made to the same minutes, the minute editor conflict UI can execute attacker-controlled script in the viewer's browser in the Indico origin. This issue is fixed in version 3.3.13.
Indico is an event management system that uses Flask-Multipass, a multi-backend authentication system for Flask. Prior to 3.3.13, users who can manage events or create content, including speakers who can upload material, can store crafted javascript URLs in fields that accept custom URLs. A user who follows one of these URLs can execute attacker-controlled script in the user's browser in the Indico origin. This issue is fixed in version 3.3.13.
Indico: Missing access check in legacy session export API
Indico is an event management system that uses Flask-Multipass, a multi-backend authentication system for Flask. Prior to 3.3.13, an authenticated user can misuse the legacy session export API to retrieve details for a restricted session without access to that session, as long as the containing event is accessible. The missing access check can disclose session metadata such as the title, description, and conveners. This issue is fixed in version 3.3.13.
Indico is an event management system that uses Flask-Multipass, a multi-backend authentication system for Flask. Prior to 3.3.13, the previous fix for CVE-2026-25738 did not cover an edge case, allowing an event organizer to submit a crafted URL that points to a prohibited local target but is accepted as valid by Indico. The organizer can read data returned by the target through affected Indico features. This issue is fixed in version 3.3.13.
CairoSVG: Quadratic-time DoS parsing a crafted SVG <path>
CairoSVG is an SVG converter based on Cairo, a 2D graphics library. Prior to 2.9.1, rendering an attacker-controlled SVG with a path containing many segments can cause quadratic CPU consumption in cairosvg/path.py. The path tokenizer repeatedly slices and rescans the remaining path data, while draw_markers drains node.vertices with node.vertices.pop(0), causing repeated linear-time work. The svg2png, svg2pdf, and svg2ps APIs reach these operations during ordinary rendering, allowing a sub-megabyte SVG to consume substantial CPU and deny service to a rendering application. This issue is fixed in version 2.9.1.
datamodel-code-generator: Protobuf weak-import path traversal allows files to be written outside the temporary directory
datamodel-code-generator generates Python data models from schema definitions. From 0.59.0 until 0.81.0, an attacker-controlled Protobuf schema can supply absolute or parent-directory paths captured by WEAK_IMPORT_PATTERN and consumed by _write_missing_weak_imports in src/datamodel_code_generator/parser/protobuf.py. Exploitation requires a victim or automated job to process the attacker-controlled schema with Protobuf input support, which requires the grpcio-tools package. The paths escape the weak_imports temporary directory before protoc runs, allowing creation of directory trees and new files or overwrite of existing writable files with a
`pydantic-ai-slim` web UI `/api/chat` accepts browser-simple cross-origin requests that can trigger agent tool execution
Pydantic AI is a Python agent framework for building applications and workflows with Generative AI. From 1.34.0 until 1.107.4 and 2.28.0, the Agent.to_web() and clai web development chat endpoint has missing request content-type validation. A website visited by a developer can submit a browser-compatible request to a loopback-hosted chat server, causing the served agent to run and execute tools with the privileges and credentials of the local process; client-relayed approval decisions also leave requires_approval=True tools exposed. Binding to localhost does not prevent a browser page from reaching the loopback address. This issue is fixed in