-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Add security best practices page. #1820
Conversation
@mandiwise is attempting to deploy a commit to the The GraphQL Foundation Team on Vercel. A member of the Team first needs to authorize it. |
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.
This is going to be a super valuable resource and one the community will refer to time and time again - thanks so much for your work on it! ✨ It reads really well and covers most of the important stuff without getting too bogged down in technical detail; I've noted a few minor issues with precision and have made a few suggestions for improvement below.
Co-authored-by: Benjie <[email protected]>
Co-authored-by: Benjie <[email protected]>
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.
Looks good to me! Excited to get this out there 🙌 🎉
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
src/pages/learn/security.mdx
Outdated
|
||
As a build step during development clients may submit their GraphQL documents to the server's allowlist, where each document is stored with a unique ID—usually its hash. At runtime, the client can send a document ID instead of the full GraphQL document, and the server will only execute requests for known document IDs. | ||
|
||
Trusted documents are simply _persisted documents_ that are deemed to not be malicious, usually because they were authored by your developers and approved through code review. Efforts are underway to [standardize _persisted documents_ as part of the GraphQL-over-HTTP specification](https://github.com/graphql/graphql-over-http/pull/264)—an increasing number of GraphQL clients and servers already support them (sometimes under their legacy misnomer: _persisted queries_). |
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.
people also call these persisted operations
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.
Also "stored queries" and "stored operations" (and maybe "stored documents", but I don't recall that?) have been used. I think that's too much detail to include in these docs though; "persisted queries" is sufficiently pervasive to warrant mentioning but the others can be glossed over.
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.
Very exciting to have this content here!
I would also maybe take this opportunity to link from the article to sections of tools and libraries that are related to the concepts in the article?
We can add a section call "security" under https://graphql.org/community/tools-and-libraries/ and link it 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.
Some suggestions :)
Depending on the client implementation, query batching can be a useful strategy for limiting the number of round trips to a server to fetch all of the required data to render a user interface. However, there should be an upper limit on the total number of queries allowed in a single batch. | ||
|
||
As with depth limiting, a GraphQL implementation may have configuration options to restrict operation breadth, field alias usage, and batching. | ||
|
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.
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.
A GraphQL API cannot have recursive fragments, as stated by the GraphQL specification:
https://spec.graphql.org/draft/#sec-Fragment-Spreads-Must-Not-Form-Cycles
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.
Interesting thanks!
Note: seems like it’s not always implemented properly — a CVE we found with our team.
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.
That definitely seems like a bug in that implementation, missing one of the core validation rules is quite a major diversion from the spec - I would expect that to be opt-in.
It would be really good to get the https://github.com/graphql-cats/graphql-cats project (or one like it) up and running again so it can be checked if an implementation is actually spec-compliant. If anyone was interested in taking this on, I'm fairly sure it would likely get approval from the community grant program.
Depth, breadth, and batch limiting help prevent broad categories of malicious operations such as cyclic queries and batching attacks, but they don't provide a way to declare that a particular field is computationally expensive to resolve. So for more advanced demand control requirements, you may wish to implement rate limiting. | ||
|
||
Rate limiting may take place in different layers of an application, for example, in the network layer or the business logic layer. Because GraphQL allows clients to specify exactly what data they need in their queries, a server may not be able to know in advance if a request includes fields that will place a higher load on its resources during execution. As a result, applying useful rate limits for a GraphQL API typically requires a different approach than simply keeping track of the total number of incoming requests over a time period in the network layer; therefore applying rate limits within the business logic layer is generally recommended. | ||
|
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.
|
||
Even though the overall depth of this query is shallow, the underlying data source for the API will still have to handle a large number of requests to resolve data for the aliased `hero` field. | ||
|
||
Similarly, a client may send a GraphQL document with many batched operations in a request: |
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.
Is batching
standard to GraphQL? I think it's not in the official specification: https://spec.graphql.org/October2021/
It's only on some GraphQL clients.
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.
The official specification doesn't even cover HTTP. We're in the process of specifying batching as part of the GraphQL-over-HTTP working group:
[Introspection](/learn/introspection/) is a powerful feature of GraphQL that allows you to query a GraphQL API for information about its schema. However, GraphQL APIs that only serve first-party clients may forbid introspection queries in non-development environments. | ||
|
||
Note that disabling introspection can be used as a form of "security through obscurity," but will not be sufficient to entirely obscure a GraphQL API by itself. It may be used as a part of a broader security strategy to limit the discoverability of API information from potential attackers. For more comprehensive protection of sensitive schema details and user data, trusted documents and authorization should be used. | ||
|
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.
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.
This is one of many many ways of extracting schema information despite introspection being disabled, I worry if we list this as an example then people will think they just need to solve that too and then they're good - they're not. Ultimately: GraphQL schemas should not be treated as secrets/if your schema is secret then it should not accept arbitrary operations (i.e. you should use trusted documents).
If you're interested, a little more information on this topic can be found in my GraphQLConf 2024 talk; here's a timestamped link to the relevant part: https://youtu.be/Ytt1_ZIlYdg?t=1267
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.
"Looking over the shoulder" is a fun one ;)
But that's totally true!
And Nice talk and thanks for the various mentions 🙏
Thanks for taking the time to review @iCarossio 🙌 |
I believe Uri's feedback has been addressed - the remaining action point I've filed an issue about: @iCarossio Please follow up with any suggested edits as PRs - ideally separate PRs for each topic so we can discuss each on its own grounds. Perhaps for some of the examples you propose it might make sense to add them via Thanks for your feedback everyone, and for your work on this Mandi - I'm going to go ahead and merge! 🎉 |
I believe Uri's suggestions have been adopted.
Co-authored-by: Benjie <[email protected]>
Addresses a todo in #41
Description
This PR adds a new security best practices page with content on transport layer security, demand control, and schema considerations.
@benjie @jorydotcom