Mitigation Strategy: Query Depth Limiting with MaxDepthRule
-
Description:
- Identify Maximum Depth: Analyze your GraphQL schema and determine the maximum reasonable nesting depth. Start conservatively (e.g., 5-7).
- Implement
MaxDepthRule
: Use theAddValidationRule
method within yourAddGraphQL
configuration to add the built-inMaxDepthRule
.services.AddGraphQL(b => b .AddSchema<MySchema>() .AddValidationRule(new MaxDepthRule(10)) // Example: Limit to 10 );
- Test: Create queries exceeding the limit and verify rejection. Test valid queries within the limit.
- Monitor and Adjust: Monitor logs for rejected legitimate queries and adjust the limit if needed.
-
List of Threats Mitigated:
- Denial of Service (DoS) via Deeply Nested Queries: (Severity: High)
- Resource Exhaustion: (Severity: High)
-
Impact:
- Denial of Service (DoS): Risk significantly reduced.
- Resource Exhaustion: Risk significantly reduced.
-
Currently Implemented: Yes / Partially / No (Specify) - Provide details.
-
Missing Implementation: If "Partially" or "No" above, describe where it's missing.
Mitigation Strategy: Query Complexity Limiting with MaxComplexityRule
or Custom Analyzer
-
Description:
- Choose a Complexity Metric: Decide on a metric (cost-per-field or custom logic).
- Assign Costs: (If using
MaxComplexityRule
) Assign costs to fields, considering list fields, complex queries, external services, and impactful arguments. - Implement the Rule: Use
AddValidationRule
withMaxComplexityRule
or a customIDocumentValidator
.// Example using MaxComplexityRule services.AddGraphQL(b => b .AddSchema<MySchema>() .AddValidationRule(new MaxComplexityRule(1000, (context, node) => { if (node is Field field) { return field.Definition.ResolvedType is ListGraphType ? 10 : 1; } return 0; })) );
- Set a Complexity Limit: Determine a reasonable maximum complexity score.
- Test and Refine: Test with varying complexity levels. Monitor and adjust costs/limit.
-
List of Threats Mitigated:
- Denial of Service (DoS) via Complex Queries: (Severity: High)
- Resource Exhaustion: (Severity: High)
- Performance Degradation: (Severity: Medium)
-
Impact:
- Denial of Service (DoS): Risk significantly reduced.
- Resource Exhaustion: Risk significantly reduced.
- Performance Degradation: Risk reduced.
-
Currently Implemented: Yes / Partially / No (Specify) - Provide details.
-
Missing Implementation: If "Partially" or "No" above, describe where it's missing.
Mitigation Strategy: Introspection Control
-
Description:
- Assess Introspection Needs: Determine if introspection is needed in production.
- Disable Introspection (if applicable): Set
EnableSchemaPrinting
tofalse
inExecutionOptions
.services.AddGraphQL(options => { if (Environment.IsProduction()) { options.EnableSchemaPrinting = false; } });
- Implement
ISchemaFilter
(if partial introspection is needed):- Create a class implementing
ISchemaFilter
. - In the
Filter
method, useISchemaFilterContext
toIgnore
types/fields/arguments. - Register the
ISchemaFilter
usingAddSchemaFilter
.
// Example ISchemaFilter public class MySchemaFilter : ISchemaFilter { public void Filter(ISchemaFilterContext context) { context.Ignore(context.Schema.AllTypes.FirstOrDefault(t => t.Name == "InternalType")); } } services.AddGraphQL(b => b.AddSchemaFilter<MySchemaFilter>());
- Create a class implementing
- Test: Verify introspection is disabled or partially restricted.
-
List of Threats Mitigated:
- Information Disclosure: (Severity: Medium)
- Schema Enumeration: (Severity: Medium)
-
Impact:
- Information Disclosure: Risk significantly reduced/eliminated.
- Schema Enumeration: Risk significantly reduced/eliminated.
-
Currently Implemented: Yes / Partially / No (Specify) - Provide details.
-
Missing Implementation: If "Partially" or "No" above, describe where it's missing.
Mitigation Strategy: Disable Field Suggestions
-
Description:
- Locate Configuration: Find
ExecutionOptions
in yourAddGraphQL
configuration. - Disable Suggestions: Set
EnableSuggestions
tofalse
.services.AddGraphQL(b => b .ConfigureExecutionOptions(options => { options.EnableSuggestions = false; }) );
- Test: Send a query with an invalid field and verify no suggestions are provided.
- Locate Configuration: Find
-
List of Threats Mitigated:
- Information Disclosure (Minor): (Severity: Low)
-
Impact:
- Information Disclosure (Minor): Risk eliminated.
-
Currently Implemented: Yes / Partially / No (Specify) - Provide details.
-
Missing Implementation: If "Partially" or "No" above, describe where it's missing.
Mitigation Strategy: Customized Error Handling
-
Description:
- Identify Sensitive Information: Determine what shouldn't be exposed in errors.
- Implement
UnhandledExceptionDelegate
: SetUnhandledExceptionDelegate
inExecutionOptions
.services.AddGraphQL(b => b .ConfigureExecutionOptions(options => { options.UnhandledExceptionDelegate = async context => { // Log internally _logger.LogError(context.OriginalException, "GraphQL error"); context.ErrorMessage = "An unexpected error occurred."; // Generic message await Task.CompletedTask; }; }) );
- Log Exceptions Internally: Log full exception details internally, not to the client.
- Return Generic Error Messages: Return generic messages to the client.
- Consider Error Codes: Use standardized error codes for client handling.
- Use
AddErrorInfoProvider
: Use for more control over error formatting, setExposeExceptionStackTrace
tofalse
.services.AddGraphQL(b => b .AddErrorInfoProvider(opt => opt.ExposeExceptionStackTrace = false) );
- Test: Trigger errors and verify non-revealing messages.
-
List of Threats Mitigated:
- Information Disclosure via Error Messages: (Severity: Medium)
-
Impact:
- Information Disclosure via Error Messages: Risk significantly reduced.
-
Currently Implemented: Yes / Partially / No (Specify) - Provide details.
-
Missing Implementation: If "Partially" or "No" above, describe where it's missing.
Mitigation Strategy: Apply Per-Operation Limits within Batches (if batching is enabled)
-
Description:
- Access Operations in Batch: Within your
MaxComplexityRule
,MaxDepthRule
or customIDocumentValidator
, access the individual operations within a batched query. TheDocument
property of theIValidationContext
will contain aDocument
with multipleOperationDefinition
nodes if it's a batch request. - Iterate and Validate: Iterate through each
OperationDefinition
within theDocument
. Apply your complexity and depth checks to each operation individually. - Aggregate Results (if needed): If you need to track a total complexity across the entire batch (in addition to per-operation limits), you can accumulate the complexity scores within your validation rule.
- Test: Send batched queries with varying numbers and complexities of operations to ensure per-operation limits are enforced.
//Example within a custom IDocumentValidator public class MyCustomValidator : DocumentValidator { public override ValueTask<INodeVisitor> ValidateAsync(ValidationContext context) { return new ValueTask<INodeVisitor>(new MyVisitor(context)); } } public class MyVisitor: INodeVisitor{ private readonly ValidationContext _context; public MyVisitor(ValidationContext context){ _context = context; } public void Enter(ASTNode node){ if (node is Document doc) { foreach (var operation in doc.Definitions.OfType<OperationDefinition>()) { // Apply your per-operation complexity/depth checks here int depth = CalculateDepth(operation); // Example: Custom depth calculation if (depth > 10) // Example limit { _context.ReportError(new ValidationError( _context.Document.Source, "operation-depth", $"Operation exceeds maximum depth of 10. Depth: {depth}", operation )); } } } } public void Exit(ASTNode node){} private int CalculateDepth(ASTNode node) { // Implement your depth calculation logic here // ... (recursive function to traverse the AST) ... return 0; // Placeholder } } //Register in services services.AddGraphQL(b => b.AddValidator<MyCustomValidator>());
- Access Operations in Batch: Within your
-
List of Threats Mitigated:
- Denial of Service (DoS) via Batching: (Severity: High)
- Resource Exhaustion: (Severity: High)
-
Impact:
- Denial of Service (DoS) via Batching: Risk significantly reduced.
- Resource Exhaustion: Risk significantly reduced.
-
Currently Implemented: Yes / Partially / No (Specify) - Provide details.
-
Missing Implementation: If "Partially" or "No" above, describe where it's missing.
Mitigation Strategy: Proper DataLoader Configuration (if used)
-
Description:
- Understand DataLoader: Familiarize yourself with the
DataLoader
pattern and its use ingraphql-dotnet
. - Identify N+1 Problems: Analyze resolvers for potential N+1 query problems.
- Implement DataLoaders: Create
DataLoader
instances for fields prone to N+1 problems, using batching to fetch data efficiently. - Configure Batching: Ensure correct
DataLoader
configuration for batching requests. - Test: Use a profiler/logging to verify reduced database queries.
- Monitor: Regularly monitor performance.
- Understand DataLoader: Familiarize yourself with the
-
List of Threats Mitigated:
- Performance Degradation (N+1 Problem): (Severity: Medium)
- Resource Exhaustion (Database): (Severity: Medium)
-
Impact:
- Performance Degradation (N+1 Problem): Risk significantly reduced.
- Resource Exhaustion (Database): Risk significantly reduced.
-
Currently Implemented: Yes / Partially / No (Specify) - Provide details.
-
Missing Implementation: If "Partially" or "No" above, describe where it's missing.