HarperFast / HarperFast/harper

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

Open
#1,291 3 comments 0 reactions 0 assignees View on GitHub
area:GraphQL area:security enhancement
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## 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)._

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.