Class: Scryer::Rules::GraphqlMissingQueryLimitsRule
- Inherits:
-
Scryer::Rule
- Object
- Scryer::Rule
- Scryer::Rules::GraphqlMissingQueryLimitsRule
- Defined in:
- lib/scryer/rules/graphql_missing_query_limits_rule.rb
Overview
Flags a class X < GraphQL::Schema (or a class whose superclass
constant path text is exactly GraphQL::Schema) whose body calls
neither max_depth nor max_complexity anywhere — without at least
one of those, a client can send an arbitrarily deep/expensive query
and the server will try to resolve all of it, a common
denial-of-service vector for GraphQL APIs. Both missing is flagged as
a single finding per class (not one per missing directive), the same
"did the class do the safe thing at all" pattern as
ActiveStorageMissingContentTypeValidationRule/IdorRule.
Constant Summary collapse
- LIMIT_METHODS =
%w[max_depth max_complexity].freeze
Instance Attribute Summary
Attributes inherited from Scryer::Rule
Instance Method Summary collapse
Methods inherited from Scryer::Rule
Constructor Details
This class inherits a constructor from Scryer::Rule
Instance Method Details
#scan ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/scryer/rules/graphql_missing_query_limits_rule.rb', line 20 def scan findings = [] Ast.each_node(sexp) do |node| next unless Ast.tagged?(node, :class) superclass = superclass_name(node[2]) next unless superclass == "GraphQL::Schema" body = node[3] next if each_call_names(body).any? { |name| LIMIT_METHODS.include?(name) } class_name = Ast.ident_text(node[1].is_a?(Array) ? node[1][1] : nil) line = Ast.line_of(node) findings << finding( line: line, message: "`#{class_name}` extends `GraphQL::Schema` but calls neither `max_depth` nor " \ "`max_complexity` — without either limit, a client can send an arbitrarily " \ "deep or expensive query and the server will attempt to resolve all of it, a " \ "common denial-of-service vector for GraphQL APIs.", suggested_fix: "Add at least one limit to the schema, e.g. `max_depth 15` and/or " \ "`max_complexity 300` (tune both to what this API's real queries need)." ) end findings end |