AppSync Security Improvements

AWS recently announcement some additional configuration settings for AppSync. These new settings allow you to control the query complexity and restrict schema introspection. Using these settings will help you stop people from abusing your GraphQL API.

Schema introspection is a mechanism where a GraphQL client can see the types and fields supported by your GraphQL API. Having this enabled during development allows clients to check their queries are valid and that return types match. On production they are less useful and could provide an information allowing someone to craft an attack against your API.

You can now disable GraphQL schema introspection on your AppSync API to prevent this information from being discovered.

AWS has also added the ability to limit the depth of a query. Let's imagine you have the following schema:

type Author {
  id: ID!
  firstName: String
  lastName: String
  books: [Book]
}

type Book {
  id: ID!
  title: String
  authors: [Author]
}

type Query {
  authors: [Author]
  books: [Book]
}

When the schema was designed you only imagined that people would either query all books and the authors who wrote them or all authors and the books they wrote.

Using schema introspection an attacker could discover that there is a loop in the schema between Author and Book then craft a deep query like this:

query {
  authors {
    id
    firstName
    lastName
    books {
      id
      title
      authors {
        id
        firstName
        lastName
        books {
          id
          title
          authors {
            id
            firstName
            lastName
            books {
              id
              title
              authors {
                id
                firstName
                lastName
                books {
                  id
                  title
                  authors {
                    id
                    firstName
                    lastName
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

This query serves no purpose other than tying up resources on the server and costing money. While I've limited the query to 10 levels deep someone using an automated tool could make this many levels deeper and attempt to run hundreds of API requests simultaneously.

By limiting the depth of the query you can stop this type of attack.

The final new setting limits the number of resolvers that will be executed during the query. Limiting the depth of a query might stop someone from taking advantage of loops in your API but it doesn't stop them from executing a wide request. For example:

query {
  authors {
    id
    firstName
    lastName
    books {
      id
      title
    }
  }
  books {
    id
    title
    authors {
      id
      firstName
      lastName
    }
  }
}

By limiting the number of resolvers executed during a query you can stop these wide requests. Once the maximum number of resolvers has been executed the API will error.

All of these settings are important in keeping your API safe from automated attacks. Schema introspection should be disabled immediately on product and limiting query depth is typically also a quick win. If you didn't design your schema to include pagination then you should focus on adding that before you try limiting the maximum number of resolvers executed as it will be hard to come up with a reasonable number.