Absinthe Graphql nested queries security

555 views Asked by At

I've been reading that it is important to secure your applications with the a Maximum Query Depth. Meaning, to limit the number of "levels" that the query has. Example of a very deep query:

query IAmEvil {
  author(id: "abc") {
    posts {
      author {
        posts {
          author {
            posts {
              author {
                # that could go on as deep as the client wants!
              }
            }
          }
        }
      }
    }
  }
}

How can I know the level of depth of my query? and ultimately not allowed queries with more that a depth of 4 to perform. Can I get the full query to count the deepness manually? Or is their already an implementation?

This problem is also described here: https://www.howtographql.com/advanced/4-security/

2

There are 2 answers

0
Marcos Tapajós On

You can write a middleware to check the selection_depth and block it. Something like that:

@impl Absinthe.Middleware
def call(res, _config) do
  IO.inspect(selection_depth(res.definition.selections))
  res
end

def selection_depth([], depth), do: depth + 1
def selection_depth(selections, depth \\ 0),
  do: selections |> Enum.map(&selection_depth(&1.selections, depth + 1)) |> Enum.max()
0
nico On

One way to handle this could be to use Absinthe's complexity analysis feature. You can declare a static complexity or a function that will be used to calculate a dynamic complexity, for each field, and set a max complexity.

An error will be returned if the query reaches the max complexity.

See the official docs for more info: https://hexdocs.pm/absinthe/complexity-analysis.html