We are releasing a major version for DGS to address a CSRF vulnerability. This version adds a breaking change for callers that target the GraphQL Endpoint, /graphql
by default, and don't explicit set the content-type
to be one of either application/json
, application/graphql
, or multipart/form-data
, the latter use for file upload. If a client is using multipart/form-data
they will now need to include a preflight header that matches any of "x-apollo-operation-name", "apollo-require-preflight", or "graphql-require-preflight".
TL;DR
- DGS will only accept requests with
content-type
of application/json
, application/graphql
, and multipart/form-data
.
- DGS will enforce a preflight header if the
content-type
is multipart/form-data
. Acceptable preflight headers are "x-apollo-operation-name", "apollo-require-preflight", or "graphql-require-preflight"
Application developers should provide a sensible CORS policy, doing so is out of scope of the DGS framework but available via Spring Boot and Spring Security.
Although not recommended you can disable the preflight check by setting dgs.graphql.header.validation.enabled
to false
.
Context
There could be a potential CSRF attacks that can leverage the execution of JS code attached to a content-type: multipart/form-data
, or other content-types which will not force the browsers to do a preflight check and enforce the CORS policy. Application developers should provide a sensible CORS policy as well as, if they use cookies, a sensible cookie SameSite policy.
DGS MVC supports the execution of GraphQL operations via HTTP POST requests with content-type: multipart/form-data
. Because they are POST requests, they can contain GraphQL mutations. Because they use content-type: multipart/form-data
, they can be "simple requests" which are not preflighted by browsers.
Spring Boot applications using DGS that set SameSite=None
cookies for authentication are then open to JS code from any origin can that can cause browsers to send cookie-authenticated
Mutations to the GraphQL endpoint, this will then be executed without checking your CORS policy first. Although the attack won't be able to see the response to the mutation if your CORS policy is set up properly, the side effects of the mutation will still occur.
In addition, if the Spring Boot application using DGS relies on network properties for security (whether by explicitly looking at the client's IP address or by only being available on a private network), then JS on any origin can cause browsers (which may be on a private network or have an allowed IP address) to send mutations to your GraphQL server, which will be executed without checking your CORS policy first. (This attack does not require your server to use cookies. It is in some cases prevented by some browsers such as Chrome.)
For additional context visit Apollo Server 2 graphql-upload CSRF Page.
⭐ Special thanks to the Apollo Server Team for identifying the CSRF. ⭐
What’s Changed
- CSRF attack mitigation on requests with multipart/form-data, plain-text, or empty content-types (#1073) @berngp
Source code(tar.gz)
Source code(zip)