#9789·keystone

Should Keystone enforce GraphQL query depth limits by default?

Author: n0wshCreated Mar 18, 2026Updated Mar 23, 2026

Context

Multiple independent security researchers (myself and @nedlir) have independently identified that Keystone's GraphQL API has no query depth limiting, complexity analysis, or cost budgeting.

A single unauthenticated request with a deeply-nested circular relationship query (e.g. users → posts → author → posts → author → ...) triggers exponential database queries. In local testing against a SQLite database with 6 total records, a depth-16 query caused a 38-second server hang.

This is classified as CWE-400: Uncontrolled Resource Consumption.

What other GraphQL frameworks do

Framework Default depth limit Complexity analysis
Hasura Yes (built-in) Yes
PostGraphile Configurable Yes (cost analysis)
graphql-ruby max_depth + max_complexity Yes
Lighthouse (Laravel) Yes (configurable) Yes
Keystone None None

Reproduction

Any Keystone project with bidirectional relationships (the standard pattern):

graphql
# No authentication required (with allowAll access)
{
  users {
    posts {
      author {
        posts {
          author {
            posts {
              author {
                posts {
                  author { id }
                }
              }
            }
          }
        }
      }
    }
  }
}

Measured response times (SQLite, 1 user + 5 posts + 15 comments):

Depth Time
12 0.9s
14 4.2s
16 38s (timeout)

Proposal

Add a default query depth limit (e.g. 10) using graphql-depth-limit or equivalent, with a configuration option:

typescript
export default config({
  graphql: {
    maxDepth: 10, // default, configurable
  },
})

Questions

  1. Should Keystone ship with a default query depth limit?
  2. Should this be treated as a security advisory or a hardening improvement?
  3. What default depth limit would be appropriate?

cc @nedlir @dcousens