CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-107727

CVE-2026-107727: Connection-Level Denial of Service via State Leak in Strawberry GraphQL Legacy WS Handler

Alon Barad
Alon Barad
Software Engineer

Oct 9, 2026·6 min read·5 visits

Executive Summary (TL;DR)

A state leak in Strawberry GraphQL's legacy WebSocket handler causes naturally completed subscriptions to permanently consume connection slots under max_subscriptions_per_connection, enabling remote attackers to deny future subscription requests on persistent sessions.

An uncontrolled resource consumption vulnerability in Strawberry GraphQL allows unauthenticated remote attackers to trigger a Denial of Service on persistent WebSocket connections using the legacy graphql-ws protocol. When the server enforces max_subscriptions_per_connection, naturally terminating subscriptions are not cleared from memory registries, leading to exhaustion of connection slots.

Vulnerability Overview

Strawberry GraphQL is a Python library designed for building GraphQL APIs using type hints. Among its features, Strawberry supports real-time subscriptions over WebSockets. In asynchronous network environments, subscription endpoints often expose a substantial attack surface, as persistent connections consume system resources like memory sockets and task descriptors over extended periods. To protect these resources, developers can enforce limits such as max_subscriptions_per_connection to control the allocation of active streams per connection.

The vulnerability resides within Strawberry's implementation of the legacy graphql-ws WebSocket subscription protocol handler, specifically in the file strawberry/subscriptions/protocols/graphql_ws/handlers.py. This component manages the lifecycle of subscription generators and their corresponding execution tasks. However, under configurations where a connection-level subscription limit is enforced, the handler does not maintain clean lifecycle tracking.

Classified under CWE-400 (Uncontrolled Resource Consumption), the defect allows an attacker to exhaust the configured subscription capacity of a single persistent WebSocket connection. Because the internal registry fails to release reference mappings when subscriptions naturally terminate or complete, subsequent query operations on that connection are blocked. This creates a localized, application-level Denial of Service (DoS) condition on the affected session.

Root Cause Analysis

To execute subscriptions, Strawberry spawns asynchronous generators wrapped in asyncio.Task objects. The legacy graphql-ws handler tracks these operations using two distinct internal dictionary attributes: self.subscriptions, which maps an operation identifier to the active execution generator, and self.tasks, which maps the operation identifier to the driving asyncio.Task loop.

When a client issues a stop command, the handler invokes cleanup_operation(operation_id). This function closes the underlying generator, cancels the associated task, and deletes both dictionary entries. However, the handler handles naturally terminating subscriptions (such as single-yield subscriptions or finished query streams) through a different execution path inside the handle_async_results coroutine.

When a subscription completes naturally, the async for loop in handle_async_results terminates, and the handler transmits a CompleteMessage to the client. In the vulnerable versions, the function exits without performing any dictionary cleanup. Although the execution task has completed and exited the event loop, its reference persists within self.tasks and self.subscriptions. If the client submits multiple consecutive completed operations using unique IDs, the self.tasks mapping grows monotonically, eventually exhausting the limit specified by max_subscriptions_per_connection and blocking all subsequent subscription requests on that connection.

Code and Flow Analysis

The state leak within the execution pathway of the legacy handler is illustrated by the following diagram:

The vulnerability is located within the handle_async_results coroutine before the implementation of the patch. In the vulnerable version, the final execution path lacked any mechanism to clean up the bookkeeping entries when the loop finished running:

# Vulnerable code in strawberry/subscriptions/protocols/graphql_ws/handlers.py
async def handle_async_results(
    self, 
    operation_id: str, 
    result_source: AsyncIterator[ExecutionResult]
) -> None:
    try:
        async for result in result_source:
            await self.send_message(DataMessage(type="data", id=operation_id, ...))
        # Natural termination point of the generator loop
        await self.send_message(CompleteMessage(type="complete", id=operation_id))
        # [CRITICAL FLAW] Missing dictionary cleanup for self.subscriptions and self.tasks
    except asyncio.CancelledError:
        await self.send_message(CompleteMessage(type="complete", id=operation_id))

The official fix resolved this omission by introducing a finally block to ensure dictionary cleanup under all termination scenarios, and by refactoring the cleanup_operation function to utilize safe, non-raising .pop() methods:

# Patched code in strawberry/subscriptions/protocols/graphql_ws/handlers.py
async def handle_async_results(
    self, 
    operation_id: str, 
    result_source: AsyncIterator[ExecutionResult]
) -> None:
    try:
        async for result in result_source:
            await self.send_message(DataMessage(type="data", id=operation_id, ...))
        await self.send_message(CompleteMessage(type="complete", id=operation_id))
    except asyncio.CancelledError:
        await self.send_message(CompleteMessage(type="complete", id=operation_id))
    finally:
        # Ensure the bookkeeping is released upon any exit path
        self.subscriptions.pop(operation_id, None)
        self.tasks.pop(operation_id, None)

This remediation provides complete coverage because python guarantees the execution of the finally block, whether the coroutine completes normally, receives a cancellation signal, or raises an unhandled exception. This design ensures that task counts cannot be artificially inflated.

Exploitation Methodology

Exploitation of this vulnerability requires that the target server utilizes the legacy graphql-ws sub-protocol and has max_subscriptions_per_connection configured to a non-zero integer. No authentication or special privileges are required to initiate the attack sequence.

An attacker initiates a standard WebSocket handshake targeting the /graphql route, requesting the graphql-ws sub-protocol during negotiation. Once connection acknowledgment is received, the attacker begins issuing sequential subscription initiation payloads using distinct id values. Each payload requests a query or subscription that immediately finishes, such as a query yielding a single static value.

After each sequence, the server returns the requested payload followed by a complete message. Because of the state leak, the server retains the mapping for each unique operation ID. After sending a number of operations equal to the server's configured limit, any subsequent start commands issued on that WebSocket connection are met with a Subscription limit reached error message. This effectively denies the user session the ability to perform legitimate operations until the connection is terminated and re-established.

Impact Assessment

The overall security impact of CVE-2026-107727 is classified as low, as reflected by its CVSS base score of 3.7. The vulnerability represents an availability-only risk (A:L) and does not threaten data confidentiality or integrity. Furthermore, exploitation is constrained to the attacker's own persistent connection session.

In standard deployment configurations, an attacker cannot target other users' active WebSockets. However, in deployments that utilize shared connection models, multiplexing reverse-proxies, or persistent connection pooling where multiple client logical sessions share a physical socket connection, the risk of cross-user impact increases. In such scenarios, an attacker can intentionally exhaust the pool, causing denial of service to other users sharing the gateway.

Because of the low impact and the high prerequisite of requiring legacy subscription configurations, the vulnerability has an extremely low EPSS score of 0.35%. It is not known to be exploited in the wild, nor is it associated with any active ransomware campaigns. However, it represents an architectural flaw that can cause operational instability under benign client usage patterns if client applications perform frequent subscription teardowns and initializations over persistent connections.

Remediation and Mitigation

The primary resolution for CVE-2026-107727 is upgrading the Strawberry GraphQL library to version 0.327.2 or later, which incorporates the proper task release logic inside the execution handler.

If upgrading is not immediately possible, three primary mitigations can be implemented:

  1. Disable the connection cap setting by removing the configuration value for max_subscriptions_per_connection on the GraphQL server endpoint. While the dictionary memory leak will still occur, the server will no longer block subsequent incoming subscriptions.

  2. Migrate to the modern, specification-compliant graphql-transport-ws protocol, which is unaffected by this state-tracking bug and is natively supported by modern GraphQL clients.

  3. Implement a client-side workaround that explicitly transmits a legacy stop frame whenever a subscription completes or yields its final payload, forcing the server to trigger its cleanup_operation subroutine.

Official Patches

strawberry-graphqlPull Request containing fix code and lifecycle unit tests.
strawberry-graphqlFix commit implementing the robust finally block cleanup in the legacy handler.

Fix Analysis (1)

Technical Appendix

CVSS Score
3.7/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
EPSS Probability
0.35%
Top 73% most exploited

Affected Systems

Strawberry GraphQL

Affected Versions Detail

Product
Affected Versions
Fixed Version
Strawberry GraphQL
strawberry-graphql
>= 0.312.3, < 0.327.20.327.2
AttributeDetail
CWE IDCWE-400
Attack VectorNetwork (AV:N)
CVSS v3.1 Score3.7 (Low)
EPSS Score0.0035 (Percentile: 26.60%)
Exploit StatusPoC available
CISA KEV StatusNot listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-400
Uncontrolled Resource Consumption

The product does not properly control the allocation and maintenance of a limited resource, enabling an actor to influence the amount of resources consumed.

Known Exploits & Detection

GitHub Security AdvisoryThe advisory details the root cause and provides execution workflow examples that trigger the connection block.

References & Sources

  • [1]GitHub Security Advisory GHSA-m952-2w3f-6r8h
  • [2]Strawberry GraphQL Pull Request #4610
  • [3]Fix Commit 24c5e46d57f7ad4f77e6e01fb8ae482dd1c0ff92
  • [4]Strawberry GraphQL Release 0.327.2
  • [5]Official CVE.org Listing
  • [6]NVD Directory Entry

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•13 minutes ago•CVE-2026-107728
7.5

CVE-2026-107728: Authorization Bypass in Strawberry GraphQL Permission Validation

An authorization bypass vulnerability in Strawberry GraphQL between versions 0.217.0 and 0.326.1 occurs when a synchronous permission handler returns an awaitable object (such as an unawaited coroutine). Due to Python's truthiness rules, the unawaited coroutine is evaluated as True, leading to an immediate bypass of security policies.

Amit Schendel
Amit Schendel
0 views•5 min read
•about 2 hours ago•CVE-2026-107723
8.1

CVE-2026-107723: Silent Claim-Validator Bypass in NearForm fast-jwt via Array Payload Type Confusion

A high-severity type-confusion vulnerability exists in NearForm fast-jwt prior to version 6.3.0. The vulnerability allows attackers to bypass crucial claim validation steps (such as expiration, issuer, audience, and subject validations) by presenting a validly signed JSON Web Token structured as a JSON array instead of a JSON object. This occurs because the library's decoder fails to reject JSON arrays during type evaluation.

Alon Barad
Alon Barad
7 views•6 min read
•about 3 hours ago•CVE-2026-107721
5.9

CVE-2026-107721: Time Validation Bypass in NearForm fast-jwt due to Loose Temporal Option Validation

NearForm fast-jwt prior to version 6.3.0 is vulnerable to an input validation flaw where configuring verifier properties (such as clockTolerance, clockTimestamp, and cacheTTL) with non-finite values like Infinity or NaN allows attackers to bypass temporal claim validations, including expiration (exp) and activation (nbf) boundaries. This validation bypass can result in unauthorized session persistence and cache poisoning.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 4 hours ago•CVE-2026-107722
9.8

CVE-2026-107722: Algorithm Confusion via Non-Whitespace Prefix Bypass in fast-jwt

A critical cryptographic vulnerability in fast-jwt versions 6.2.x prior to 6.3.0 allows unauthenticated remote attackers to execute an asymmetric-to-symmetric algorithm confusion attack due to incomplete validation of leading non-whitespace prefixes.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 5 hours ago•CVE-2026-107720
7.4

CVE-2026-107720: Signature Verification Bypass in NearForm fast-jwt

CVE-2026-107720 is a critical signature verification bypass vulnerability in NearForm's fast-jwt Node.js library. Under specific configurations where the token verifier is initialized with a falsy cryptographic key (such as an empty string or null) and a non-empty algorithms allowlist, the library erroneously skips signature validation. This allows unauthenticated remote attackers to submit fabricated, unsigned JSON Web Tokens and bypass the authorization boundary of the application entirely.

Amit Schendel
Amit Schendel
7 views•7 min read
•about 6 hours ago•CVE-2026-107715
6.8

CVE-2026-107715: Information Disclosure and Credential Leakage in Ruby Mechanize via Cross-Origin Redirections

Ruby Mechanize prior to version 2.14.1 contains an information disclosure vulnerability. When executing cross-origin HTTP redirects, global headers configured on the Mechanize agent (such as Authorization or Session Cookies) are dynamically re-applied to the subsequent request, bypassing the internal header-stripping logic. An attacker who controls a redirection endpoint can capture sensitive bearer tokens or cookies.

Alon Barad
Alon Barad
7 views•7 min read