GraphQL is a powerful tool, but with great power come great security risks. One of the biggest advantages of GraphQL is that you are able get data across multiple resources within a single request. This allows the potential attacker to make complex queries that quickly result in resource exhaustion. In this brief article we will go through some tips to minimize these risks and secure your GraphQL schema against potential attackers.
Use https and do not forget about https redirect
Disable introspection in production
Resource exhaustion prevention
I think the biggest issue in GraphQL (especially if you want to open the schema to the public) comes with its biggest advantage, and that is the ability to query for various sources with a one single request. However, there are certain concerns about this feature. The issue is that potential attackers can easily call complex queries, which may be extremely expensive for your server and network. We can reduce the load on the database a lot by batching and caching with Data Loader. Load on the network, however, can not be reduced easily and has to be restricted. There are various ways to limit capabilities of the attacker to execute malicious queries. In my opinion, the most important and useful methods are the following:
- Rejecting based on query complexity (cost analysis) great for public schema, but needed even for queries behind authorization. A great library for this use case is graphql-cost-analysis as it also provides different cost analysis rules based on the query and not for the whole schema.
- Amount limiting restrict the amount of objects someone is able to fetch from the database. Instead of fetching every object, it’s better to use cursor based pagination.
- Depth limiting block recursive queries, which are too costly. Usually limiting the amount to depth 10 is good enough.
There are many more methods you can implement, but the combination of these three you will cover most cases of malicious queries. None of these methods will solve the problem for every query. Therefore we need to implement a combination of these methods. We will include a detailed explanation with implementation in future articles, so be sure to subscribe.
Use npm audit in your CI
One of the biggest security issues in your Node.js project is that you can accidentally use a malicious package or a package with security holes. The danger exists not only for lesser known npm packages as described in this article, but also for the packages with a large user base. Let’s take the example of the latest incident, which affected the package eslint-scope, which in turn is dependent on some widely used packages like babel-eslint and webpack, see postmortem. In this incident the the credentials of one of the the contributors were compromised, and then the new version of the packages with malicious code was published. You will never be able to defend yourself fully if you use some external packages, but you can significantly decrease the risk by using npm audit in your continuous integration pipeline.
The list definitely does not end here. This is only a small subset of security concerns that you need to consider when deploying your GraphQL app to production. To really dive deeper into these topics with the practical code snippets on implementing all security concerns, you can subscribe to our GraphQL newsletter, where you will receive info about the newest articles on GraphQL Mastery and also updates on our upcoming GraphQL courses. Meanwhile, you can take a look at our free GraphQL language course.
Feel free to send any questions about this article or GraphQL Mastery in general to firstname.lastname@example.org. You can also check out our upcoming free GraphQL language course or subscribe for new articles on GraphQL Mastery with the form below. If you prefer you can also checkout republished medium version of the article.