mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 12:44:15 +03:00
feat: max depth
Signed-off-by: QuentinN42 <quentin@lieumont.fr>
This commit is contained in:
parent
18b7d53428
commit
84c5559ded
|
@ -2,14 +2,23 @@
|
|||
Security consideration
|
||||
======================
|
||||
|
||||
In this section, we will discuss the most common security risks and how to mitigate them.
|
||||
|
||||
As GraphQL is a query language, it allows users to use a wider pannel of inputs than traditional REST APIs.
|
||||
Due to this feature, GraphQL APIs are inherently prone to various security risks, but they can be reduced by taking
|
||||
appropriate precautions. Neglecting them can expose the API to vulnerabilities like credential leakage or denial of
|
||||
service attacks.
|
||||
|
||||
In this section, we will discuss the most common security risks and how to mitigate them.
|
||||
As Graphene is only an engine to run GraphQL queries, it is not responsible for the HTTP layer and this security must be
|
||||
handled by the web framework you are using. For example, if you are using Django-GraphQL, you may also want to check out
|
||||
the `Django documentation`_ on how to secure your API.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
maxdepth
|
||||
queryvalidation
|
||||
|
||||
We have seen the most efficient way to secure your GraphQL API.
|
||||
|
||||
.. _Django documentation: https://docs.djangoproject.com/en/4.1/topics/security/
|
||||
|
|
75
docs/security/maxdepth.rst
Normal file
75
docs/security/maxdepth.rst
Normal file
|
@ -0,0 +1,75 @@
|
|||
Depth limit Validator
|
||||
=====================
|
||||
|
||||
By default, GraphQL queries can be arbitrarily deep. This can lead to a denial of service attack where a client can send
|
||||
a deeply nested query that will take a long time to execute. For that, you must find a cycle in the graph and iterate
|
||||
over.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
For example a simple app that allows you to find your friends and their friends can lead to this query :
|
||||
|
||||
.. code:: graphql
|
||||
|
||||
query {
|
||||
me {
|
||||
friends {
|
||||
friends {
|
||||
friends {
|
||||
friends {
|
||||
...
|
||||
# dumping the whole database
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
This is not a common use case, your dev team will not do that in the first place. But as your endpoint is publicly
|
||||
available, you can't be sure that someone will not try to do so.
|
||||
|
||||
Remediation
|
||||
-----------
|
||||
|
||||
Graphene provides a depth limit validator that can be used to prevent this kind of attack. It can be configured to limit
|
||||
the depth of all the queries or only some specific ones. The only required argument is ``max_depth`` which is the
|
||||
maximum allowed depth for any operation in a GraphQL document. The other optional parameters are the following ones :
|
||||
|
||||
- ``ignore``: A list of patterns that, if matched stops recursive depth checking. It can be one of the following :
|
||||
- ``Callable : (dict[str, int]) -> bool``: A function that receives the current operation and returns a boolean.
|
||||
- ``Pattern``: A compiled regex pattern that is matched against the operation name.
|
||||
- ``str``: An operation name.
|
||||
- ``callback: (dict[str, int]) -> None`` Called each time validation runs. Receives an Object which is a map of the depths for each operation.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Here is an example of how you would implement depth-limiting on your schema.
|
||||
|
||||
.. code:: python
|
||||
|
||||
from graphql import validate, parse
|
||||
from graphene import ObjectType, Schema, String
|
||||
from graphene.validation import depth_limit_validator
|
||||
|
||||
|
||||
class MyQuery(ObjectType):
|
||||
name = String(required=True)
|
||||
|
||||
|
||||
schema = Schema(query=MyQuery)
|
||||
|
||||
# queries which have a depth more than 20
|
||||
# will not be executed.
|
||||
|
||||
validation_errors = validate(
|
||||
schema=schema.graphql_schema,
|
||||
document_ast=parse('THE QUERY'),
|
||||
rules=(
|
||||
depth_limit_validator(
|
||||
max_depth=20
|
||||
),
|
||||
)
|
||||
)
|
|
@ -7,47 +7,6 @@ makes query fail with "Cannot query field on type" error if it doesn't.
|
|||
To help with common use cases, graphene provides a few validation rules out of the box.
|
||||
|
||||
|
||||
Depth limit Validator
|
||||
---------------------
|
||||
The depth limit validator helps to prevent execution of malicious
|
||||
queries. It takes in the following arguments.
|
||||
|
||||
- ``max_depth`` is the maximum allowed depth for any operation in a GraphQL document.
|
||||
- ``ignore`` Stops recursive depth checking based on a field name. Either a string or regexp to match the name, or a function that returns a boolean
|
||||
- ``callback`` Called each time validation runs. Receives an Object which is a map of the depths for each operation.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Here is how you would implement depth-limiting on your schema.
|
||||
|
||||
.. code:: python
|
||||
|
||||
from graphql import validate, parse
|
||||
from graphene import ObjectType, Schema, String
|
||||
from graphene.validation import depth_limit_validator
|
||||
|
||||
|
||||
class MyQuery(ObjectType):
|
||||
name = String(required=True)
|
||||
|
||||
|
||||
schema = Schema(query=MyQuery)
|
||||
|
||||
# queries which have a depth more than 20
|
||||
# will not be executed.
|
||||
|
||||
validation_errors = validate(
|
||||
schema=schema.graphql_schema,
|
||||
document_ast=parse('THE QUERY'),
|
||||
rules=(
|
||||
depth_limit_validator(
|
||||
max_depth=20
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Disable Introspection
|
||||
---------------------
|
||||
the disable introspection validation rule ensures that your schema cannot be introspected.
|
||||
|
|
Loading…
Reference in New Issue
Block a user