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

Improve Security of GraphiQL #508

Merged
merged 10 commits into from
Mar 16, 2019
37 changes: 22 additions & 15 deletions graphene_django/templates/graphene/graphiql.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

// Collect the URL parameters
var parameters = {};
window.location.search.substr(1).split('&').forEach(function (entry) {
window.location.hash.substr(1).split('&').forEach(function (entry) {
var eq = entry.indexOf('=');
if (eq >= 0) {
parameters[decodeURIComponent(entry.slice(0, eq))] =
Expand All @@ -41,7 +41,7 @@
});
// Produce a Location query string from a parameter object.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment isn't quite right anymore

function locationQuery(params) {
return '?' + Object.keys(params).map(function (key) {
return '#' + Object.keys(params).map(function (key) {
return encodeURIComponent(key) + '=' +
encodeURIComponent(params[key]);
}).join('&');
Expand Down Expand Up @@ -100,22 +100,29 @@
function updateURL() {
history.replaceState(null, null, locationQuery(parameters));
}
// Render <GraphiQL /> into the body.
ReactDOM.render(
React.createElement(GraphiQL, {
fetcher: graphQLFetcher,
// If there are any fragment parameters, confirm the user wants to use them.
var isReload = window.performance ? performance.navigation.type === 1 : false;
if (Object.keys(parameters).length
&& !isReload
&& !window.confirm("An untrusted query has been loaded, continue loading query?")) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth including an explanation of why running an untrusted query might be a bad idea, and what damage it could cause.

Also something like "if you're not sure click cancel"

This is the Facebook devtools warning for eg:

Stop!

This is a browser feature intended for developers. If someone told you to copy and paste something here to enable a Facebook feature or "hack" someone's account, it is a scam and will give them access to your Facebook account.

See https://www.facebook.com/selfxss for more information.

parameters = {};
}
var options = {
fetcher: graphQLFetcher,
onEditQuery: onEditQuery,
onEditVariables: onEditVariables,
onEditOperationName: onEditOperationName,
query: '{{ query|escapejs }}',
response: '{{ result|escapejs }}',
{% if variables %}
variables: '{{ variables|escapejs }}',
{% endif %}
{% if operation_name %}
operationName: '{{ operation_name|escapejs }}',
{% endif %}
}),
query: parameters.query,
}
if (parameters.variables) {
options.variables = parameters.variables;
}
if (parameters.operation_name) {
options.operationName = parameters.operation_name;
}
// Render <GraphiQL /> into the body.
ReactDOM.render(
React.createElement(GraphiQL, options),
document.body
);
</script>
Expand Down
19 changes: 6 additions & 13 deletions graphene_django/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ def dispatch(self, request, *args, **kwargs):
data = self.parse_body(request)
show_graphiql = self.graphiql and self.can_display_graphiql(request, data)

if show_graphiql:
return self.render_graphiql(
request,
graphiql_version=self.graphiql_version,
)

if self.batch:
responses = [self.get_response(request, entry) for entry in data]
result = "[{}]".format(
Expand All @@ -137,19 +143,6 @@ def dispatch(self, request, *args, **kwargs):
else:
result, status_code = self.get_response(request, data, show_graphiql)

if show_graphiql:
query, variables, operation_name, id = self.get_graphql_params(
request, data
)
return self.render_graphiql(
request,
graphiql_version=self.graphiql_version,
query=query or "",
variables=json.dumps(variables) or "",
operation_name=operation_name or "",
result=result or "",
)

return HttpResponse(
status=status_code, content=result, content_type="application/json"
)
Expand Down