-
Notifications
You must be signed in to change notification settings - Fork 65
Revise non-normative notes section #345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -276,7 +276,7 @@ accepting both media types, the client SHOULD indicate it prefers | |
For HTTP GET requests, the _GraphQL-over-HTTP request_ parameters MUST be | ||
provided in the query component of the request URL, encoded in the | ||
`application/x-www-form-urlencoded` format as specified by the | ||
[WhatWG URLSearchParams class](https://url.spec.whatwg.org/#interface-urlsearchparams). | ||
[WHATWG URLSearchParams class](https://url.spec.whatwg.org/#interface-urlsearchparams). | ||
|
||
The {query} parameter MUST be the string representation of the source text of | ||
the document as specified in | ||
|
@@ -291,7 +291,7 @@ The {operationName} parameter, if supplied and not the empty string, represents | |
the name of the operation to be executed within the {query} as a string. | ||
|
||
Note: In the final URL all of these parameters will appear in the query | ||
component of the request URL as URL-encoded values due to the WhatWG | ||
component of the request URL as URL-encoded values due to the WHATWG | ||
URLSearchParams encoding specified above. | ||
|
||
Setting the value of the {operationName} parameter to the empty string is | ||
|
@@ -757,41 +757,79 @@ etc. | |
|
||
# Non-normative notes | ||
|
||
This section of the specification is non-normative, even where the words and | ||
phrases specified in RFC2119 are used. | ||
|
||
## Security | ||
|
||
In this specification, GET requests are not supported for mutations due to | ||
security concerns. GET requests expose variables to logging mechanisms and | ||
intermediaries due to the URL encoding of parameters, which can lead to | ||
sensitive data being inadvertently logged. Furthermore, GET requests are | ||
considered "simple requests" under CORS (Cross-Origin Resource Sharing), meaning | ||
they bypass preflight checks that add a layer of security. | ||
|
||
On the other hand, using `application/json` for request bodies mandates a CORS | ||
preflight request, adding a security layer by ensuring the client has explicit | ||
permission from the server before sending the actual request. This is | ||
particularly important in mitigating cross-site request forgery (CSRF) attacks. | ||
|
||
It's important to note that "simple requests" like those using | ||
`application/x-www-form-urlencoded` or `multipart/form-data` do not have the | ||
same CORS behavior, and thus do not undergo the same preflight checks. | ||
Implementers should be aware of the security implications of using these types | ||
of requests. While they can be secured with the right headers enforced by the | ||
server, it is crucial to understand and properly account for the security risks | ||
involved. | ||
|
||
To mitigate these risks, it is recommended that servers require a custom header | ||
to ensure requests are not "simple." For instance, a `GraphQL-Require-Preflight` | ||
header can be used to indicate that a preflight check has occurred, providing an | ||
additional layer of security. | ||
This specification focuses solely on the intersection of GraphQL and HTTP. | ||
General concerns of either technology, including security concerns, are out of | ||
scope, except where their interaction introduces additional considerations. | ||
|
||
### HTTP | ||
|
||
Implementers are expected to have a solid understanding of the security | ||
implications of exposing a service over HTTP, and are responsible for | ||
implementing relevant mitigations and solutions. This specification will not | ||
repeat standard HTTP best practices such as not using `GET` for requests with | ||
side effects, safe logging of requests without revealing sensitive information, | ||
ensuring all connections are encrypted via HTTPS, placing limits on the length | ||
of incoming data, implementing rate limits, authorization and authentication | ||
security, request tracing, intrusion detection, and so on. | ||
|
||
### GraphQL | ||
|
||
Implementers are further expected to have a solid understanding of the security | ||
implications of running a GraphQL service and are responsible for implementing | ||
relevant mitigations and solutions there. For example, they may: limit the size | ||
and token count of GraphQL documents; ensure document validity; limit the number | ||
of errors a response may return; limit information revealed via errors; enforce | ||
validation and execution timeouts and pagination limits; implement query depth | ||
and complexity limits; implement authentication and authorization; apply rate | ||
limits to critical logic; and so on. | ||
|
||
### Exercise caution | ||
|
||
Where this specification leaves flexibility for the implementer, the implementer | ||
should be very cautious when exercising this freedom. Implementers must make | ||
themselves aware of and account for the security implications of their choices; | ||
while many alternative choices can be secured, securing them is outside of the | ||
scope of this specification. | ||
|
||
For example, this specification allows alternative media types to be used to | ||
encode the request body; however, media types such as `multipart/form-data` or | ||
`application/x-www-form-urlencoded` may result in the request being treated by a | ||
browser as a "simple request", which does not require a "preflight", thereby | ||
opening the server up to Cross-Site Request Forgery (CSRF/XSRF) attacks. The | ||
recommended `application/json` media type requires a "preflight" check when | ||
issued cross-domain. See | ||
[CORS protocol](https://fetch.spec.whatwg.org/#http-cors-protocol) in the WHATWG | ||
Fetch spec for more details on this. | ||
|
||
Note: One approach used by the community to mitigate CSRF risks is to ensure a | ||
request is not "simple" by requiring a custom header—such as | ||
`GraphQL-Require-Preflight`—is included. The presence of a custom header forces | ||
browsers to enact a "preflight" check, thereby adding an additional layer of | ||
security. (This is not a standard header, and many alternative headers could | ||
serve the same purpose. This is presented merely as an example of a pattern seen | ||
in the community.) | ||
Comment on lines
+809
to
+815
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about strengthening the suggestion of the header name to be used here, to help the community settle on a single header within servers that support There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not convinced that requiring a preflight is a good security practice; the vast majority of GraphQL APIs IMO should either be closed off entirely (no cross-origin requests, first party only, trusted documents), or they should not support any credentials caching that a preflight would be relevant to (include all credentials in the request, none implicit). The <1% of use cases that fall outside of this should have their own experts who know what to do. Given that, I don't want us to be seen as standardizing one because it looks like we're also giving the approach legitimacy that I'm not sure it warrants. IMO it's a workaround to poor architectural choices or restrictions. |
||
|
||
Further extending this example, using `multipart/form-data` may allow large | ||
values to be referenced multiple times in a GraphQL operation, potentially | ||
causing the GraphQL service to process a much larger GraphQL request than the | ||
HTTP request size would suggest. | ||
|
||
### Other resources | ||
|
||
For more detailed security considerations, please refer to | ||
[RFC 7231](https://tools.ietf.org/html/rfc7231), | ||
[RFC 6454](https://tools.ietf.org/html/rfc6454), and other relevant RFCs. | ||
[RFC 6454](https://tools.ietf.org/html/rfc6454), other relevant RFCs, and other | ||
resources such as [OWASP](https://owasp.org). | ||
|
||
## Request format compatibility | ||
## Future compatibility | ||
|
||
Supporting formats not described by this specification, such as XML or Protobuf, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed these examples because I didn't want to imply that we might (or might not) be expanding to these formats in future. Clearer to exclude them IMO. |
||
may have potential conflicts with future versions of this specification as | ||
ongoing development aims to standardize and ensure the security and | ||
interoperability of GraphQL over HTTP. For this reason, it is recommended to | ||
adhere to the officially recognized formats outlined here. | ||
Supporting formats not described by this specification may have potential | ||
conflicts with future versions of this specification as ongoing development aims | ||
to standardize and ensure the security and interoperability of GraphQL over HTTP | ||
whilst accounting for its growing feature set. For this reason, it is | ||
recommended to adhere to the officially recognized formats outlined here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that this PR still retains explicit comments regarding the use of
multipart/form-data
, as this is not evident by the rest of the RFC and is important enough to worth of being explicitly noted, as it was/is a common practice.