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):
# 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:
export default config({
graphql: {
maxDepth: 10, // default, configurable
},
})
Questions
- Should Keystone ship with a default query depth limit?
- Should this be treated as a security advisory or a hardening improvement?
- What default depth limit would be appropriate?
cc @nedlir @dcousens
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
max_depth+max_complexityReproduction
Any Keystone project with bidirectional relationships (the standard pattern):
Measured response times (SQLite, 1 user + 5 posts + 15 comments):
Proposal
Add a default query depth limit (e.g. 10) using
graphql-depth-limitor equivalent, with a configuration option:Questions
cc @nedlir @dcousens