-
Notifications
You must be signed in to change notification settings - Fork 822
Protection against malicious queries #907
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
Comments
I have recently been looking into exactly these same things. It would be great to have something built in available, and if not, at least some examples of how someone might best implement these with graphene. |
@Arfey this is an area where there aren't any official answers in Graphene at the moment but I'll give you my opinion on the approaches that you've listed: 1 and 2: query cost or resource limitations + limiting query depthIn another issue I've written up some sample code (not thoroughly tested) that will implement a basic max query depth check: #772 (comment) Something similar could be used for query cost calculations but it's unclear to mean how you would determine the cost of particular fields. I think there is opportunity for experimentation in user space for this. 3. query whitelistingThe backend functionality is also the place to implement any kind of persisted/query whitelisting. I actually don't think this feature is within the scope of the Graphene project though because it's going to be tightly coupled to the rest of your application. You would need to define where the persisted queries are stored, how the front end part of your app adds new queries, how your server interprets static queries etc. Again this is a place where experimentation can happen in userland and Graphene already exposes the right hooks through backends to implement it. 4. hide introspection for production modeThis sounds like a reasonable suggestion and I think it could be implemented. Any thoughts @graphql-python/core @graphql-python/governors ? |
yes, i will make pull request some time later |
Just my completely unasked for $.02: About 3, I think it would help if the types that are automatically generated (from SQLAlchemy or Django ORM models) had their fields explicitly included instead of explicitly excluded. Much like how Django's own ModeField works. Instead of class MyType(SQLAlchemyObjectType):
class Meta:
model = MyModel
exclude_fields = ('scary_field',) this: class MyType(SQLAlchemyObjectType):
class Meta:
model = MyModel
include_fields = ('safe_field',) while making the absence of both |
Hiding introspection won't help much if the attacker has access to a copy of a client application, as she would be able to guess enough of the schema to write custom queries - just one cycle in the graph is enough for an attack. |
I use middleware for that right now class HideIntrospectMiddleware:
"""
This middleware should use for production mode. This class hide the
introspection.
"""
def resolve(self, next, root, info, **args):
if info.field_name == '__schema':
return None
return next(root, info, **args) |
Hiya, thanks for the sample code but how can I plug this into graphene please? Is it a setting I can add, something like:
? I've also tried adding it to my GraphQL view, which gives me an error when I run a query through graphiql (using the core backend)
the error is:
Update - sorted it out, needed to provide an instance not the class. I'll leave this here in case it helps someone. so to add the backend, I've done:
|
My $.02 for how I handle this: I have different types in the Schema with different related-node-information based on where the type is being used. This artificially sets a query depth which is dependent on the query. E.g. If authors have one more books:
This works for small to medium sized applications and doesn't take much thought/code to get working. |
Thanks @thejcannon - agreed, it makes a lot of sense just design the api not to have cycles in it. Still nice to know no one is able to run queries that join many distinct tables on my server. @jkimbo - can I check something on the code sample you provided please:
This suggests we're only interested in queries, but since a mutation could return an object (like an authentication mutation might return a user object) does it not make sense to run this on both? Wondering if there is some subtlety I'm missing. |
@sandwichsudo that is a good point, I can't remember why I added that line but I think you could probably just omit it and it would still work. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
I am using this validation rule to disable schema introspection: class NoIntrospection(ValidationRule):
def enter_Field(self, node, key, parent, path, ancestors):
field_name = node.name.value
if field_name == "__schema" or field_name == "__type":
self.context.report_error(
GraphQLError(u"GraphQL introspection is not allowed", [node])
) |
@sboisson I found this snippet:
Seems like there is more introspection keywords - I think you should be checking for those too. On a more general note: More security tools for this would be nice. Adding to the initial list:
|
@fwirtz Nice find! |
@sboisson yeah I found that catch afterwards as well haha. |
Any update on this matter? I found this repo of someone trying to work on this, for now it implements the least interesting part of it (limiting query depth). I'm really new to this so I don't know if this could help. By the way, is it possible to add a middleware directly to a |
Can anyone enlighten me why schema introspection is a flaw? I use graphene-django, and I only expose non-private fields using |
@melvinkcx it's not strictly a flaw, it's a risk:
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Not stale |
there are two projects which aim to solve this problem:
|
@jkimbo backends are being removed in Graphene v3. |
We could either implement a middleware or, I think better it is a better way, a custom validation rule: |
@CodeByAryan : @devkral is right, using validation rules is the best way of doing this. I've add support for that in Strawberry here: strawberry-graphql/strawberry#1021 Feel free to reuse the code for a Graphene project. It should work with any graphql-core based library. |
thanks for the replies @jkimbo @devkral I've raised an issue here. edit: I've also submitted a PR. Please review it! edit 2: guys, jkimbo merged the PR! |
Hey. I was looking for a lot of information on how to protect against malicious requests, and as a result I found several common approaches:
All this approaches we can implement by meddleware and custom backend. But it will be cool if this solution is out of the box.
Also, graphene don't have information about security into the documentation.
ps: I can try to help, but if u have no reason why this is a bad idea.
The text was updated successfully, but these errors were encountered: