Find your way in GraphQL applications - Paths explained

One GraphQL benefit over REST is that you can define a generic backend to serve applications.

GraphQL defines its data schema, explicitly providing which object lives in the current application and operations to query these objects.

Introduction

Let's start with an example schema.

type User {
    name: String!
    organization: String!
}

type Query {
	getUser(name: String!): User
}


// Query getUser -> User
Basic GraphQL Schema

Here, we created a User data structure and made it accessible through the query getUser.

Many backends rely on permissions management, and misunderstanding GraphQL specifications can lead to flaws or harmful data leaks.


The reference problem

So far, the schema we defined remains very simple, but we could add an Organization data structure that references a User.

GraphQL Circular reference (using GraphQL Voyager)

This unsafe reference will create an infinite loop and an enumeration flaw.

These flaws won't directly affect developers or lead to data leaks. But you may run into permissions issues.

For example, we could have checked the authorization to fetch User using getUser, but did restrict the fetch of Organization to getOrganization query.


GraphQL Complexity

GraphQL applications tend to be bigger than rest, coming to the number of paths when REST uses a fixed number of routes.

The language defines and supports complex links like Unions and Interfaces to provide a highly configurable backend.

For example, using Union and defining the following schema:

type Query {
	getCharacter(name: String!): CharacterTypes!
}

union CharacterTypes = Droid | Human

type Droid {
	...
}

type Human {
	...
}
GraphQL Schema that contains Union

You, in fact, created two paths for one query!

Query getCharacter -> Droid
Query getCharacter -> Human

By hand, auditing applications are time-consuming and likely to grow exponentially with the size of the schema.


Enumerating the paths

You can always explore the result of an introspection query by using GraphQL Voyager and better understand your defined paths.

GraphQL Voyager SWAPI Schema

Our goal at Escape is to make the GraphQL world safer. To do so, we need to ensure that every path on a GraphQL backend are scanned.

We recently open-sourced a python module, graphenum that serves this specific need.

Maybe you also want to automate the path enumeration to perform some coverage checks on your application? Or even just referencing them to do full profiling?

Graphenum is a tool that will introspect and convert a GraphQL specification into an exploitable JSON file along with the path referencing an object, a bunch of statistics, and property census.


Conclusion

GraphQL specification and its underneath recursivity could create a layer of obstruction and technical debt for your developers.

Make sure you understand the insights of this model to unleash all its power and make your applications more secure.

References:

Code used in this article: https://github.com/Escape-Technologies/blog-posts/tree/main/find-your-way-in-graphql

GraphQL Voyager (Represent any GraphQL API as an interactive graph) : https://ivangoncharov.github.io/graphql-voyager/

Setup a GraphQL Yoga application: https://www.graphql-yoga.com/tutorial/basic

Awesome GraphQL Security: https://github.com/Escape-Technologies/awesome-graphql-security

Add GraphQL security layer for Apollo/Yoga: https://github.com/Escape-Technologies/graphql-armor

Wanna know more about automated GraphQL security testing? Read our blog article "How to test your GraphQL API?".