You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reject GET requests with a Content-Type other than application/json (#8191)
GET requests carry their GraphQL operation in query parameters, not a
body, so there is no legitimate reason to send any Content-Type other
than application/json (which Apollo Client Web sends by default). Reject
any other value — including valid MIME types like text/plain and
application/graphql, as well as malformed values — with HTTP 415.
This also addresses
GHSA-9q82-xgwf-vj6h
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Security**
* Strengthened CSRF protection: GET requests with `Content-Type` headers
other than `application/json` are now rejected (HTTP 415)
* Users with cookies or HTTP Basic Auth should upgrade to v5.5.0
* **Documentation**
* Updated request handling and CSRF prevention documentation
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Apollo Server now rejects GraphQL `GET` requests which contain a `Content-Type` header other than `application/json` (with optional parameters such as `; charset=utf-8`). Any other value is now rejected with a 415 status code.
9
+
10
+
(GraphQL `GET` requests without a `Content-Type` header are still allowed, though they do still need to contain a non-empty `X-Apollo-Operation-Name` or `Apollo-Require-Preflight` header to be processed if the default CSRF prevention feature is enabled.)
11
+
12
+
This improvement makes Apollo Server's CSRF more resistant to browsers which implement CORS in non-spec-compliant ways. Apollo is aware of one browser which as of March 2026 has a bug which allows an attacker to circumvent Apollo Server's CSRF prevention feature to carry out read-only XS-Search-style CSRF attacks. The browser vendor is in the process of patching this vulnerability; upgrading Apollo Server to v5.5.0 mitigates this vulnerability.
13
+
14
+
**If your server uses cookies (or HTTP Basic Auth) for authentication, Apollo encourages you to upgrade to v5.5.0.**
15
+
16
+
This is technically a backwards-incompatible change. Apollo is not aware of any GraphQL clients which provide non-empty `Content-Type` headers with `GET` requests with types other than `application/json`. If your use case requires such requests, please [file an issue](https://github.com/apollographql/apollo-server/issues) and we may add more configurability in a follow-up release.
17
+
18
+
See [advisory GHSA-9q82-xgwf-vj6h](https://github.com/apollographql/apollo-server/security/advisories/GHSA-9q82-xgwf-vj6h) for more details.
Copy file name to clipboardExpand all lines: docs/source/integrations/building-integrations.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -120,6 +120,8 @@ Integrations _are_ responsible for parsing a request's body and using the values
120
120
121
121
In Apollo Server's Express integration, you set up the `express.json()` JSON middleware, which handles parsing JSON request bodies with a `content-type` of `application/json`. Integrations can require a similar middleware (or plugin) for their ecosystem, or they can handle body parsing themselves.
122
122
123
+
Note that Apollo Server's [CSRF prevention](../security/cors/#preventing-cross-site-request-forgery-csrf) feature assumes that your integration's recommended method of body parsing will reject `POST` requests without a `content-type` of `application/json`. If your integration allows `POST` requests with no `content-type` header (or with a `content-type` of `text/plain`, `application/x-www-form-urlencoded`, or `multipart/form-data`), servers will be vulnerable to CSRF attacks.
124
+
123
125
For example, a correctly parsed body should have a shape resembling this:
Copy file name to clipboardExpand all lines: docs/source/security/cors.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -200,7 +200,7 @@ However, Apollo Server also handles [`GET` requests](../workflow/requests#get-re
200
200
201
201
By default, Apollo Server 4+ has a CSRF prevention feature enabled. This means your server only executes GraphQL operations if at least one of the following conditions is true:
202
202
203
-
- The incoming request includes a `Content-Type` header that specifies a type other than `text/plain`, `application/x-www-form-urlencoded`, or `multipart/form-data`. Notably, a `Content-Type` of `application/json` (including any suffix like `application/json; charset=utf-8`) is sufficient. This means that all `POST` requests (which must use `Content-Type: application/json`) will be executed. Additionally, all versions of [Apollo Client Web](/react/api/link/apollo-link-http) that support `GET` requests do include `Content-Type: application/json` headers, so any request from Apollo Client Web (`POST` or `GET`) will be executed.
203
+
- The incoming request includes a `Content-Type` header that specifies a type other than `text/plain`, `application/x-www-form-urlencoded`, or `multipart/form-data`. Notably, a `Content-Type` of `application/json` (including any suffix like `application/json; charset=utf-8`) is sufficient. This means that all `POST` requests (which must use `Content-Type: application/json`) will be executed. Additionally, all versions of [Apollo Client Web](/react/api/link/apollo-link-http) that support `GET` requests do include `Content-Type: application/json` headers, so any request from Apollo Client Web (`POST` or `GET`) will be executed. (As of v5.5.0, Apollo Server rejects GET requests which contain a non-empty `Content-Type` other than `application/json`, so in practice this bullet point could be summarized as "the incoming request includes a `Content-Type` header that specifies the type `application/json`".)
204
204
- There is a non-empty `X-Apollo-Operation-Name` header. This header is sent with all operations (`POST` or `GET`) by [Apollo iOS](/ios) (v0.13.0+) and [Apollo Kotlin](/kotlin) (all versions, including its former name "Apollo Android"), so any request from Apollo iOS or Apollo Kotlin will be executed.
205
205
- There is a non-empty `Apollo-Require-Preflight` header.
Unlike with `POST` requests, `GET` requests do not require a `Content-Type` header. However, if you have Apollo Server's default [CSRF prevention](../security/cors#preventing-cross-site-request-forgery-csrf) feature enabled, `GET` requests that don't contain a `Content-Type` header must contain one of the following:
85
+
Unlike with `POST` requests, `GET` requests do not require a `Content-Type` header: this header describes the request's body's type, and `GET` requests do not have a body. For historical reasons, Apollo Server allows `GET` requests with a `Content-Type` header of `application/json` (with optional parameters such as `; charset=utf-8`); any other value is rejected with a 415 status code.
86
+
87
+
Additionally, if you have Apollo Server's default [CSRF prevention](../security/cors#preventing-cross-site-request-forgery-csrf) feature enabled, `GET` requests that don't contain a `Content-Type` header must contain one of the following:
0 commit comments