Last active
May 20, 2021 21:59
-
-
Save benmccallum/9329bcc70711f1bc14e74dc82693c607 to your computer and use it in GitHub Desktop.
Prevent introspection queries on HotChocolate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Prevents use of certain field names typically used in introspection queries. | |
/// Useful for production environments where you may want to guard against such queries. | |
/// </summary> | |
/// <remarks> | |
/// Compatible with v10 of HotChocolate. | |
/// </summary> | |
public class NoIntrospectionValidationRule : IQueryValidationRule | |
{ | |
private static readonly HashSet<string> _bannedFieldNames = new HashSet<string>() { "__schema", "__type" }; | |
public QueryValidationResult Validate(ISchema schema, DocumentNode queryDocument) | |
{ | |
if (queryDocument.Definitions.OfType<OperationDefinitionNode>().Any(n => ContainsBannedFieldName(n.SelectionSet)) || | |
queryDocument.Definitions.OfType<FragmentDefinitionNode>().Any(n => ContainsBannedFieldName(n.SelectionSet)) || | |
queryDocument.Definitions.OfType<InlineFragmentNode>().Any(n => ContainsBannedFieldName(n.SelectionSet))) | |
{ | |
queryDocument.WithDefinitions(Array.Empty<IDefinitionNode>()); | |
var error = ErrorBuilder.New().SetMessage("Introspection queries are disabled").Build(); | |
return new QueryValidationResult(error); | |
} | |
else | |
{ | |
return QueryValidationResult.OK; | |
} | |
} | |
private bool ContainsBannedFieldName(SelectionSetNode selectionSetNode) | |
{ | |
return selectionSetNode.Selections.OfType<FieldNode>().Any(f => _bannedFieldNames.Contains(f.Name.Value)); | |
} | |
} |
@benmccallum is the last check in the if
correct?
Hey @Zero3, which version of HotChocolate are you using? This snippet is for v10, so we may need to adjust it for v11 slightly.
@benmccallum latest v10
@Zero3, I guess that like your tooling is saying, it's not a possible scenario. I'd added it to cover inline fragments, but it does make sense that they don't have a separate "definition". Might need to handle inline fragments slightly differently...
Not sure if this is the right way to do it, but I've been searching for a similar solution for v11 and came up with this:
internal class NoIntrospectionDocumentValidatorVisitor : TypeDocumentValidatorVisitor
{
protected override ISyntaxVisitorAction Enter(FieldNode node, IDocumentValidatorContext context)
{
if (node.Name.Value == IntrospectionFields.Schema || node.Name.Value == IntrospectionFields.Type)
{
IError error = ErrorBuilder.New().SetMessage("Introspection queries are disabled").Build();
context.Errors.Add(error);
return new BreakSyntaxVisitorAction();
}
return base.Enter(node, context);
}
}
Register as:
services.AddValidation()
.TryAddValidationRule<NoIntrospectionDocumentValidatorVisitor>();
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage example in Startup.cs: