mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 20:54:16 +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
|
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.
|
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
|
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
|
appropriate precautions. Neglecting them can expose the API to vulnerabilities like credential leakage or denial of
|
||||||
service attacks.
|
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::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 1
|
||||||
|
|
||||||
|
maxdepth
|
||||||
queryvalidation
|
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.
|
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
|
Disable Introspection
|
||||||
---------------------
|
---------------------
|
||||||
the disable introspection validation rule ensures that your schema cannot be introspected.
|
the disable introspection validation rule ensures that your schema cannot be introspected.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user