Jul 17, 2026·6 min read·0 visits
A Broken Object-Level Authorization (BOLA) vulnerability in MCP Python SDK allows connected clients to list, retrieve, and cancel background tasks belonging to other sessions due to a lack of context validation.
CVE-2026-52870 is a high-severity Broken Object-Level Authorization (BOLA) / Missing Authorization vulnerability (CWE-862) discovered in the experimental tasks feature of the Model Context Protocol (MCP) Python SDK. Under affected versions (< 1.27.2), default handlers registered via server.experimental.enable_tasks() allowed connected clients to enumerate, access, and terminate active tasks belonging to other user sessions due to a lack of session ownership validation. This compromised multi-tenant isolation, allowing authenticated users to extract execution data and cancel running jobs across concurrent connections. The vulnerability has been resolved in version 1.27.2 through session-scoping of task identifiers and transport session pinning.
The Model Context Protocol (MCP) Python SDK is an open-source library that facilitates standardized communication between LLM applications and external data sources or tools. In version 1.23.0, the SDK introduced an experimental tasks framework configured via server.experimental.enable_tasks(). This feature registers background execution handlers designed to list, retrieve, and cancel running tasks across client-server sessions.\n\nA critical authorization vulnerability, identified as CVE-2026-52870, exists in these registered background handlers. The default task management endpoints, specifically tasks/list, tasks/get, tasks/result, and tasks/cancel, interact with a server-wide TaskStore instance. This shared storage structure manages tasks globally across all client connections without tracking session ownership or partitioning operational access boundaries.\n\nAs a result, any client authenticated or connected to an affected MCP server can enumerate active tasks belonging to other users. Once a valid task identifier is obtained, the client can extract sensitive execution outputs or forcibly terminate active operations. This vulnerability constitutes a complete bypass of multi-tenant isolation, presenting a direct risk of data exposure and operational disruption in environments serving multiple concurrent sessions.
The root cause of CVE-2026-52870 lies in a Missing Authorization (CWE-862) or Broken Object-Level Authorization (BOLA) flaw in the task handler framework. When enable_tasks() is called, the MCP server registers default asynchronous handlers to manage background execution cycles. Historically, these handlers accepted client-supplied arguments like taskId and directly queried the shared InMemoryTaskStore without checking which session initiated the task.\n\nA fundamental operational flaw is present in how the global TaskStore processes task retrieval requests. It retrieves and mutates tasks solely using the string-based task_id (a standard UUIDv4) without checking whether the calling ServerSession matches the session that originally dispatched the task. Additionally, the tasks/list handler was configured to return a complete, un-paginated set of all active tasks globally managed by the server instance.\n\nBecause the session context was not verified at any point in the database transactional lifecycle, there was no logical separation between tenants. Any connected client could exploit this behavior to enumerate UUIDv4 identifiers through the list handler. This allowed clients to access the execution state and output objects of any other concurrent user session.
To understand the vulnerability and its remediation, analyze the design changes introduced in the fix. The original implementation queried the database purely by task_id string without verification.\n\npython\n# Affected version conceptual flow:\nasync def _default_get_task(req: GetTaskRequest) -> ServerResult:\n # No verification of session context against the task's origin session\n task = await support.store.get_task(req.params.taskId) \n return ServerResult(...)\n\n\nThe remediation introduces a regex-validated scoped identifier pattern <32_hex_chars>:<uuid4> through task_scope.py. The prefix represents an opaque task_session_scope bound to the client session. During task creation via run_task(), the SDK generates this scoped format. The default handlers are updated to extract the current requester's session scope and compare it to the requested task's embedded scope before interacting with the database.\n\npython\n# Fixed version handler enforcement:\ndef _requestor_session_scope(self) -> str | None:\n return self._server.request_context.session.experimental.task_session_scope\n\ndef _require_task_in_requestor_scope(self, task_id: str) -> None:\n # Checks if a task matches the requested session scope\n if not task_in_session_scope(task_id, self._requestor_session_scope()):\n raise McpError(\n ErrorData(\n code=INVALID_PARAMS,\n message=f\"Task not found: {task_id}\",\n )\n )\n\n\nAdditionally, tasks/list is modified to iterate through the database cursor and filter out all task models that do not carry the requestor's scope. This prevents malicious actors from enumerating adjacent tasks. Custom tasks registered with explicit, developer-supplied IDs that bypass the scoped formatting are treated as globally-accessible capabilities. However, they are entirely excluded from the task list endpoint, and the SDK generates a deprecation warning to encourage migration to session-scoped tracking.
An attack against CVE-2026-52870 requires the attacker to be a connected and authenticated client on the target MCP server. Because MCP utilizes standardized JSON-RPC 2.0 messages over Server-Sent Events (SSE) or WebSockets, an attacker can transmit raw JSON payloads using standard command-line tools or custom scripts once a session is established.\n\nmermaid\ngraph LR\n Attacker[\"Attacker Session\"] -- \"1. tasks/list\" --> Server[\"MCP Server\"]\n Server -- \"2. [victim-task-id-12345]\" --> Attacker\n Attacker -- \"3. tasks/get (victim-task-id-12345)\" --> Server\n Server -- \"4. Returns Sensitive Task Output\" --> Attacker\n Attacker -- \"5. tasks/cancel (victim-task-id-12345)\" --> Server\n Server -- \"6. Task Terminated\" --> Victim[\"Victim Session\"]\n\n\nThe attack flow begins with active task enumeration. The attacker sends a standard JSON-RPC request targeting the tasks/list method. Because the vulnerable server-wide TaskStore does not apply filtering, the response payload returns an array of task metadata, including the unique UUIDv4 task identifiers of other active sessions.\n\nWith the target task identifiers compromised, the attacker can execute two main actions. First, they can poll tasks/get or tasks/result to capture sensitive execution data, such as private tool responses, system commands, or external service keys. Second, the attacker can execute a denial-of-service attack by issuing a tasks/cancel request with the victim's task ID, terminating long-running operations and disrupting legitimate service execution.
The security impact of CVE-2026-52870 is rated as High, with a CVSS 3.1 base score of 7.6. The threat vector allows an attacker to bypass critical multi-tenant isolation boundaries. In multi-user setups, such as shared developer platforms, centralized enterprise LLM gateways, or SaaS environments, this compromise permits unauthorized access to processing pipelines.\n\nConfidentiality impact is High due to the potential exposure of execution results. Background tasks often handle proprietary data, system-level configurations, or user credentials passed through active API calls. Since the listing and retrieval methods are completely unauthenticated beyond the initial connection, any authenticated tenant can extract this data at will.\n\nIntegrity and Availability impacts are rated as Low to Moderate. While an attacker cannot write arbitrary data directly to the database or control flow, they can alter the execution state by terminating active jobs. This results in operational denial of service (DoS), particularly in environments relying on long-running computation tasks.
The primary remediation path is upgrading the mcp library within the Python deployment environment to version 1.27.2 or higher. The patch fully binds tasks to session-scoped boundaries and introduces transport-level verification to prevent session hijacking.\n\nIf an immediate upgrade is not feasible, deployment teams should temporarily disable the experimental tasks feature. This can be achieved by removing any explicit calls to server.experimental.enable_tasks() within the MCP server initialization files. Disabling the feature completely removes the vulnerable default endpoints, preventing potential exploitation.\n\nIf background tasks are required but the library cannot be upgraded immediately, developers can implement custom, context-aware authorization filters. Rather than utilizing the default handlers, developers should register custom task routers that validate user identifiers against custom database schemas. This ensures task retrieval calls verify session ownership before returning execution data.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
python-sdk Model Context Protocol | >= 1.23.0, < 1.27.2 | 1.27.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 (Missing Authorization) |
| Attack Vector | Network (AV:N) |
| CVSS Score | 7.6 (High) |
| EPSS Score | 0.00227 |
| EPSS Percentile | 13.38% |
| Impact | Multi-tenant Isolation Bypass, Information Disclosure, Denial of Service (DoS) |
| Exploit Status | Proof-of-Concept Documented |
| KEV Status | Not Listed |
The product does not perform an authorization check when an actor attempts to access a resource or perform an action.
A memory unsoundness vulnerability exists in the Diesel ORM crate when deserializing SQLite databases from raw bytes. The flaw is caused by a failure to bind the lifetime of the input buffer to the lifetime of the connection object, resulting in a Use-After-Free condition in the underlying libsqlite3 C library when subsequent queries are executed.
A high-severity privilege escalation and sandbox escape vulnerability exists in ArcadeDB Server prior to version 26.7.1. This flaw permits an authenticated user with read-only privileges to execute arbitrary JVM code in a sandboxed JavaScript context via the API command endpoint. By utilizing reflection on bound Java objects, an attacker can bypass the GraalVM guest environment's whitelist, access the Java ClassLoader, and perform arbitrary file reads on the host filesystem.
CVE-2026-59950 is a high-severity security vulnerability in the Model Context Protocol (MCP) Python SDK. Prior to version 1.28.1, the SDK's deprecated WebSocket server transport accepted incoming connection handshakes without performing validation on the Host or Origin headers. Because web browsers do not restrict WebSocket connections using the Same-Origin Policy (SOP), this enables malicious third-party websites to perform a Cross-Site WebSocket Hijacking (CSWSH) attack, executing unauthorized commands on behalf of the local user.
CVE-2026-56271 represents a critical security flaw in Flowise, an open-source visual orchestration platform for Large Language Models (LLMs) and autonomous AI agents. The vulnerability occurs within the platform's enterprise passport authentication module, where default cryptographic parameters are used in the absence of explicit environment variables. Specifically, the middleware silently falls back to known, static hardcoded secrets ('auth_token' and 'refresh_token') and identifiers ('AUDIENCE' and 'ISSUER') to generate and verify session tokens. Consequently, remote unauthenticated attackers can construct arbitrary JSON Web Tokens (JWTs) signed with these hardcoded credentials to gain administrative entry to the application.
ArcadeDB is an open-source, multi-model database engine supporting graph, document, key-value, and vector models. In affected versions of ArcadeDB, the trigger script executor improperly configures GraalVM scripting engine permissions. By allowing the 'java.lang.*' package to be loaded within the scripting context, the sandbox environment can be bypassed. An authenticated user with schema administration privileges ('UPDATE_SCHEMA') can register a malicious script trigger that executes arbitrary Java host classes, leading to unauthenticated remote command execution under the context of the ArcadeDB server process.
A critical improper access control vulnerability (CWE-284) in the WebSocket upgrade endpoint of Le Circuit Électrique charging station backend allows remote, unauthenticated attackers to connect to the Charging Station Management System and impersonate charging stations.