Skip to content
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

Protect against malicious queries #29

Open
syrusakbary opened this issue Nov 5, 2015 · 6 comments
Open

Protect against malicious queries #29

syrusakbary opened this issue Nov 5, 2015 · 6 comments

Comments

@syrusakbary
Copy link
Member

The Scala implementation of GraphQL (Sangria) provides a way for being protected against malicious queries.

More info: http://sangria-graphql.org/learn/#protection-against-malicious-queries

Could be very useful if the executor could support the following:

  • Maximum query complexity based on analysis of the query
  • Limit query depth
@millerjs
Copy link

millerjs commented Dec 4, 2015

Perhaps a first pass at this can be to allow programmers to throw exceptions which cancel the whole execution? The executor (L195) seems to swallow all exceptions. I noticed this when trying to naively limit complexity (by metric of execution time). However, there seems to be no way to short circuit the whole execution.

Related to #41.

@pobed2
Copy link

pobed2 commented Jun 26, 2017

@syrusakbary, I know this is a very old issue, but has anything been implemented to help protect against malicious queries? If not, do you have any pointers on how to implement it myself?

@dfee
Copy link
Member

dfee commented Dec 15, 2017

@pobed2 you could add a variable to your context and bump it on each resolve call. You'll probably also want a more formal data structure with a locking mechanism for the executor of your choice.

class ResolveCounter:
    def __init__(self):
        from threading import Lock
        self.count = 0
        self.max = 100
        self.lock = Lock()
    
    def increment(self):
        with self.lock():
            if self.count < self.max:
                self.count += 1
            else:
                raise RuntimeError('too many resolves')

... and then throw that into your context when you call...

schema.execute(statement, context_value={'counter': ResolveCounter()})

alternatively, you could make a helpful wrapper:

def increment_resolve_count(func):
    from functools import wraps

    @wraps(func)
    def wrapper(root, info, *args, **kwargs):
        if '_resolve_counter' not in info.context:
            info.context['_resolve_counter'] = ResolveCounter()
        resolve_counter.increment()
    return wrapper


@increment_resolve_count
def resolve_mytype(root, info):
    # your typical resolve func
    return MyType()

@dfee
Copy link
Member

dfee commented Dec 20, 2017

I thought about this after posting it, and actually I think middleware is the right place for this.

@lisongx
Copy link

lisongx commented Mar 15, 2018

this would be really hepful, the github graphql api have the node based limitation to avoid bad query coming in https://developer.github.com/v4/guides/resource-limitations/

@dan98765
Copy link
Collaborator

We're having success doing query depth limiting & node based limiting in middleware.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants