OWASP Secure Coding Cheat Sheets: GraphQL Cheat Sheet

# GraphQL Cheat Sheet

## Introduction

[GraphQL](https://graphql.org) is an open source query language originally developed by Facebook that can be used to build APIs as an alternative to REST and SOAP. It has gained popularity since its inception in 2012 because of the native flexibility it offers to those building and calling the API. There are GraphQL servers and clients implemented in various languages. [Many companies](https://foundation.graphql.org/) use GraphQL including GitHub, Credit Karma, Intuit, and PayPal.

This Cheat Sheet provides guidance on the various areas that need to be considered when working with GraphQL:

- Apply proper [input validation](Input_Validation_Cheat_Sheet.md) checks on all incoming data.
- Expensive queries will lead to [Denial of Service (DoS)](Denial_of_Service_Cheat_Sheet.md), so add checks to limit or prevent queries that are too expensive.
- Ensure that the API has proper [access control](Access_Control_Cheat_Sheet.md) checks.
- Disable insecure default configurations (_e.g._ excessive errors, introspection, GraphiQL, etc.).

## Common Attacks

- [Injection](https://github.com/OWASP/API-Security/blob/master/2019/en/src/0xa8-injection.md) - this usually includes but is not limited to:
    - [SQL](https://owasp.org/www-community/attacks/SQL_Injection) and [NoSQL](https://www.netsparker.com/blog/web-security/what-is-nosql-injection/) injection
    - [OS Command injection](https://owasp.org/www-community/attacks/Command_Injection)
    - [SSRF](https://portswigger.net/web-security/ssrf) and [CRLF](https://owasp.org/www-community/vulnerabilities/CRLF_Injection) [injection](https://www.acunetix.com/websitesecurity/crlf-injection/)/[Request](https://portswigger.net/web-security/request-smuggling) [Smuggling](https://www.pentestpartners.com/security-blog/http-request-smuggling-a-how-to/)
- [DoS](https://owasp.org/www-community/attacks/Denial_of_Service) ([Denial of Service](https://www.cloudflare.com/learning/ddos/glossary/denial-of-service/))
- Abuse of broken authorization: either [improper](https://github.com/OWASP/API-Security/blob/master/2019/en/src/0xa1-broken-object-level-authorization.md) or [excessive](https://github.com/OWASP/API-Security/blob/master/2019/en/src/0xa3-excessive-data-exposure.md) access, including [IDOR](https://portswigger.net/web-security/access-control/idor)
- Batching Attacks, a GraphQL-specific method of brute force attack
- Abuse of insecure default configurations

## Best Practices and Recommendations

### Input Validation

Adding strict input validation can help prevent against injection and DoS. The main design for GraphQL is that the user supplies one or more identifiers and the backend has a number of data fetchers making HTTP, DB, or other calls using the given identifiers. This means that user input will be included in HTTP requests, DB queries, or other requests/calls which provides opportunity for injection that could lead to various injection attacks or DoS.

See the OWASP Cheat Sheets on [Input Validation](Input_Validation_Cheat_Sheet.md) and general [injection prevention](Injection_Prevention_Cheat_Sheet.md) for full details to best perform input validation and prevent injection.

#### General Practices

Validate all incoming data to only allow valid values (i.e. allowlist).

- Use specific GraphQL [data types](https://graphql.org/learn/schema/#type-language) such as [scalars](https://graphql.org/learn/schema/#scalar-types) or [enums](https://graphql.org/learn/schema/#enumeration-types). Write custom GraphQL [validators](https://graphql.org/learn/validation/) for more complex validations. [Custom scalars](https://itnext.io/custom-scalars-in-graphql-9c26f43133f3) may also come in handy.
- Define [schemas for mutations input](https://graphql.org/learn/schema/#input-types).
- [List allowed characters](Input_Validation_Cheat_Sheet.md#allow-list-vs-block-list) - don't use a denylist
    - The stricter the list of allowed characters the better. A lot of times a good starting point is only allowing alphanumeric, non-unicode characters because it will disallow many attacks.
- To properly handle unicode input, use a [single internal character encoding](Input_Validation_Cheat_Sheet.md#validating-free-form-unicode-text)
- Gracefully [reject invalid input](Error_Handling_Cheat_Sheet.md), being careful not to reveal excessive information about how the API and its validation works.

#### Injection Prevention

When handling input meant to be passed to another interpreter (_e.g._ SQL/NoSQL/ORM, OS, LDAP, XML):

- Always choose libraries/modules/packages offering safe APIs, such as parameterized statements.
    - Ensure that you follow the documentation so you are properly using the tool
    - Using ORMs and ODMs are a good option but they must be used properly to avoid flaws such as [ORM injection](https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.7-Testing_for_ORM_Injection).
- If such tools are not available, always escape/encode input data according to best practices of the target interpreter
    - Choose a well-documented and actively maintained escaping/encoding library. Many languages and frameworks have this functionality built-in.

For more information see the below pages:

- [SQL Injection Prevention](SQL_Injection_Prevention_Cheat_Sheet.md)
- [NoSQL Injection Prevention](https://www.netsparker.com/blog/web-security/what-is-nosql-injection/)
- [LDAP Injection Prevention](LDAP_Injection_Prevention_Cheat_Sheet.md)
- [OS Command Injection Prevention](OS_Command_Injection_Defense_Cheat_Sheet.md)
- [XML Security](XML_Security_Cheat_Sheet.md) and [XXE Injection Prevention](XML_External_Entity_Prevention_Cheat_Sheet.md)

#### Process Validation

When using user input, even if sanitized and/or validated, it should not be used for certain purposes that would give a user control over data flow. For example, do not make an HTTP/resource request to a host that the user supplies (unless there is an absolute business need).

### DoS Prevention

DoS is an attack against the availability and stability of the API that can make it slow, unresponsive, or completely unavailable. This CS details several methods to limit the possibility of a DoS attack at the application level and other layers of the tech stack. There is also a CS dedicated to the topic of [DoS](Denial_of_Service_Cheat_Sheet.md).

Here are recommendations specific to GraphQL to limit the potential for DoS:

- Add depth limiting to incoming queries
- Add amount limiting to incoming queries
- Add [pagination](https://graphql.org/learn/pagination/) to limit the amount of data that can be returned in a single response
- Add reasonable timeouts at the application layer, infrastructure layer, or both
- Consider performing query cost analysis and enforcing a maximum allowed cost per query
- Enforce rate limiting on incoming requests per IP or user (or both) to prevent basic DoS attac