Published on
1 min read

GraphQL Security Issues and Solutions

Authors

The flexibility of GraphQL allows clients to define exactly what they want, but an evil client can exploit this to create deeply nested or extremely complex queries that cause resource exhaustion (DDoS).

1. Timeout

Setting a timeout ensures queries don't utilize the server longer than a specified duration. If a query exceeds the limit, GraphQL returns the partial result and rejects the rest.

# app/graphql/graphql_ruby_sample_schema.rb
GraphqlRubySampleSchema.middleware << GraphQL::Schema::TimeoutMiddleware.new(max_seconds: 10) do |err, query|
  Rails.logger.info("GraphQL Timeout: #{query.query_string}")
end
Partial Result

2. Maximum Depth

To prevent deeply nested queries, set a max_depth. The server will reject any query that exceeds this limit.

# app/graphql/graphql_ruby_sample_schema.rb
GraphqlRubySampleSchema = GraphQL::Schema.define do
  max_depth 12
end
Max Depth Error

3. Query Complexity

Complexity limits prevent resource-heavy queries by assigning a "cost" to each field. If the total complexity exceeds the limit, the query is rejected.

# app/graphql/graphql_ruby_sample_schema.rb
GraphqlRubySampleSchema = GraphQL::Schema.define do
  max_complexity 100
end

You can customize complexity for specific fields:

# Constant complexity:
field :comments, types[CommentType], complexity: 10

# Dynamic complexity:
field :top_comments, types[CommentType] do
  argument :limit, types.Int, default_value: 5
  complexity ->(ctx, args, child_complexity) {
    args[:limit] * child_complexity
  }
end

Sample code is available here.

TwitterLinkedInHacker News