Skip to content

GraphQL has no query depth/complexity/cost limit (DoS surface; dense-graph fan-out confirmed) #1291

Description

@kriszyp

Summary

The GraphQL endpoint enforces no depth, complexity, or cost limit on queries. graphql.parse(query) (server/graphqlQuerying.ts:453) is called without the library's available maxTokens cap.

  • Sparse graphs: self-referential @relationship chains execute to depth 2048 at flat 2–4ms; the only limit is accidental — at depth ~20000 the recursive parse / buildSelectQuery (graphqlQuerying.ts:286) overflows the stack → HTTP 500 Maximum call stack size exceeded (caught; worker survives; no OOM). The error is opaque (no depth/field context).
  • Dense graphs (confirmed): on a fully-connected graph, nested-query cost grows ~fanout^depth with the entire matched subtree serialized into one response and no server pushback — e.g. fanout=10 / depth 5 = 111,111 nodes in a single ~591ms response; walking past the data depth still costs seconds.

An attacker who can write a dense subgraph (or a naturally dense relationship domain) can force six-figure-node, multi-second single-request work with no rejection. No crash/OOM, but a real DoS lever.

Suggestion

Add a configurable max selection depth + complexity/cost bound, and pass maxTokens to graphql.parse; return a clear 400 (with depth/field context) rather than a 500 stack overflow or unbounded serialization.

Repro

integrationTests/qa-scratch/graphql-depth.test.ts (sparse + stack-overflow edge); integrationTests/qa-scratch/graphql-dense.test.ts (dense fan-out).


Found via the exploratory QA campaign (qa-explorer), scenarios QA-036 + QA-039. Harper 001bf7b9c (v5.1.0, main).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:GraphQLGraphQL APIarea:securitySecurity, TLS/certs, authentication, authorizationenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions