Jun 4, 2026·6 min read·8 visits
A recursive fragment loop triggers a RecursionError in Python, crashing worker threads/processes and resulting in complete Denial of Service.
An application-level Denial of Service vulnerability exists in the Strawberry GraphQL library (versions 0.71.0 through 0.315.6) due to uncontrolled recursion within the QueryDepthLimiter and MaxAliasesLimiter extensions when processing circular fragment references.
Strawberry GraphQL is an open-source Python library designed to build GraphQL APIs using type hints. The library provides optional security extensions to safeguard endpoints against resource exhaustion attacks. Two of these extensions, QueryDepthLimiter and MaxAliasesLimiter, are designed to restrict the complexity of incoming queries before execution.\n\nThese safety components are exposed to the public attack surface because they parse and validate user-supplied GraphQL queries. When an unauthenticated remote user submits a query, the validation engine processes the payload to enforce configured limits on query depth and aliases. If a query contains nested or cyclic structures, the validation logic traverses the entire document structure.\n\nA design flaw in versions prior to 0.315.7 allows an attacker to exploit the validation logic itself. By sending queries with circular fragment definitions, an attacker can bypass the safety controls and trigger an unhandled exception. This results in an application-level Denial of Service (DoS) by crashing the active Python worker thread or process.
The core issue is classified as CWE-674: Uncontrolled Recursion, which leads to CWE-400: Uncontrolled Resource Consumption. Within the QueryDepthLimiter extension, the determine_depth function traverses the selection sets of a GraphQL query. When the traversal encounters a FragmentSpreadNode, it retrieves the corresponding fragment definition and recursively invokes determine_depth to evaluate its inner depth.\n\nIn vulnerable versions of the library, the recursion occurred without tracking state or maintaining a history of previously visited nodes in the active path. The implementation did not pass a collection of traversed fragment identifiers down the call stack. Because of this omission, the algorithm cannot detect when it re-evaluates a fragment that is already present in its current call hierarchy.\n\nWhen a client submits a query where Fragment A references Fragment B, and Fragment B references Fragment A, a mutual recursion loop is established. The determine_depth function calls itself infinitely, executing until it consumes all available stack frames. Python runtime environments strictly limit the maximum recursion depth, throwing a RecursionError and terminating execution when the limit is breached.
The fix implemented in commit a69221fb0b86583ceb5755758b294c8319021fd1 introduces path-based cycle detection using Python's immutable frozenset type. This prevents infinite loop execution by tracking the names of resolved fragments across the active execution branch. The determine_depth function was updated to accept a visited_fragments parameter.\n\npython\n# Patched version of determine_depth\ndef determine_depth(\n # ... standard parameters ...\n visited_fragments: frozenset[str] | None = None,\n) -> int:\n if visited_fragments is None:\n visited_fragments = frozenset()\n\n\nDuring traversal, when a FragmentSpreadNode is encountered, the engine checks if the fragment name already exists in the visited_fragments set. If a match is found, the function returns a depth of 0 immediately, breaking the loop safely. If the fragment is unvisited, the traversal continues, appending the current fragment name to a new frozenset using the union operator.\n\npython\n if isinstance(node, FragmentSpreadNode):\n fragment_name = node.name.value\n if fragment_name in visited_fragments:\n return 0 # Break circular recursion\n\n return determine_depth(\n node=fragments[fragment_name],\n # ... other parameters ...\n visited_fragments=visited_fragments | {fragment_name},\n )\n\n\nThis pattern is highly effective because frozenset is immutable. Using the union operator (visited_fragments | {fragment_name}) passes a distinct, branch-specific copy down the recursion tree. This avoids corrupting or sharing visited state with parallel, non-cyclic sibling query branches, ensuring both correctness and safety.\n\nmermaid\ngraph LR\n A["determine_depth(A)"] --> B["determine_depth(B)"]\n B --> C["determine_depth(A) - Triggers Break"]\n
An attacker can exploit this vulnerability with a single crafted HTTP POST request containing a circular fragment reference. Since the parsing and validation phases execute before any authentication middleware or resolvers, this attack does not require valid credentials. The target endpoint must have the QueryDepthLimiter or MaxAliasesLimiter extension enabled to be vulnerable.\n\nThe exploit payload defines two fragments that mutually spread each other. For example, Fragment A references B, and Fragment B references A. A top-level query then references Fragment A. When the GraphQL validation engine processes the query, it invokes the vulnerable depth limiter logic, initiating the recursive loop.\n\ngraphql\nfragment A on User {\n ...B\n}\nfragment B on User {\n ...A\n}\nquery Exploit {\n me {\n ...A\n } \n}\n\n\nOnce submitted, the worker thread begins processing determine_depth for Fragment A, which calls Fragment B, which calls Fragment A. Within milliseconds, the stack depth exceeds Python's threshold. The resulting RecursionError escapes the validation context, crashing the underlying process and denying service to other concurrent requests.
The primary impact of CVE-2026-47706 is a complete Denial of Service (DoS) of the application layer. When Python processes throw a RecursionError during query validation, the exception is frequently unhandled by the ASGI or WSGI application servers. This triggers a hard crash of the active worker process.\n\nIn standard deployments, application servers such as Gunicorn or Uvicorn maintain a fixed pool of worker processes to handle incoming requests. If an attacker sends concurrent requests containing the circular exploit payload, they can systematically crash every available worker process in the pool. This leads to a total service outage for all users.\n\nAlthough the vulnerability does not lead to remote code execution (RCE) or data confidentiality breaches, its ease of exploitation makes it a significant operational risk. Because the validation phase occurs prior to authentication, any unauthenticated user with network access to the GraphQL endpoint can trigger the crash. The CVSS score of 5.3 reflects this focused impact on service availability.
The primary mitigation is upgrading the strawberry-graphql package to version 0.315.7 or later. This version incorporates cycle-tracking logic into both QueryDepthLimiter and MaxAliasesLimiter to safely handle cyclic structures. Organizations should verify their dependency locks and rebuild containers to ensure the patch is applied.\n\nIf upgrading is not immediately feasible, teams can disable the QueryDepthLimiter and MaxAliasesLimiter extensions as a temporary workaround. Note that disabling these extensions will expose the application to other query complexity attacks. Therefore, this action should only be taken if alternative mitigations are implemented.\n\nAn alternative workaround involves deploying a GraphQL-aware Web Application Firewall (WAF) or an API gateway (such as Apollo Router or Envoy) at the network perimeter. The gateway can be configured to validate fragment relationships and reject queries containing circular definitions before they reach the upstream Python application servers.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
strawberry-graphql Strawberry GraphQL | >= 0.71.0, <= 0.315.6 | 0.315.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-674 / CWE-400 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 5.3 (Medium) |
| Exploit Status | Proof of Concept Available |
| CISA KEV Status | Not Listed |
| Impact | Availability (Denial of Service) |
The software directs a function to call itself recursively without a mechanism to limit the recursion depth, leading to stack exhaustion.
An authentication bypass in the SiYuan personal knowledge management system before version 3.7.0 exposes a dynamic icon rendering endpoint. This endpoint processes client-supplied Go template directives. By submitting a crafted request, an unauthenticated remote attacker can leverage registered database template functions to execute arbitrary read-only SQL queries and exfiltrate workspace contents.
CVE-2026-54069 is a critical authentication bypass vulnerability in the SiYuan Note personal knowledge management system. The flaw is located in the HTTP server's middleware handling API authorization, which unconditionally trusts requests carrying a 'chrome-extension://' scheme in the Origin HTTP header, granting administrative access without validating API tokens.
CVE-2026-54089 is a critical authentication bypass vulnerability in File Browser affecting instances configured with proxy-based authentication. An unauthenticated remote attacker with direct network access can impersonate arbitrary users or register new accounts by spoofing configured HTTP headers.
The malicious Cargo package 'exploration' was uploaded to the crates.io registry. During compilation or package import, the crate executes code designed to establish an outbound TCP/HTTP connection, download an external second-stage binary, and execute the binary locally on the host machine. This creates an unauthenticated remote code execution vector impacting developer environments and continuous integration pipelines.
CVE-2026-54088 is a critical command injection vulnerability in File Browser prior to version 2.63.6. When Hook Authentication is enabled, the application interpolates unsanitized credentials into a shell command, allowing unauthenticated remote code execution.
An authenticated remote code execution vulnerability exists in NotrinosERP (versions up to and including 1.0.0) within the Human Resource Management (HRM) module. Users with employee management permissions can upload arbitrary file types, including PHP scripts, which are written directly to a web-accessible directory. This allows for arbitrary code execution in the context of the web-server user.