Skip to content

Bound GraphQL nested-filter recursion depth - #3776

Open
Souvik Ghosh (souvikghosh04) wants to merge 1 commit into
mainfrom
fix/graphql-nested-filter-depth-limit
Open

Bound GraphQL nested-filter recursion depth#3776
Souvik Ghosh (souvikghosh04) wants to merge 1 commit into
mainfrom
fix/graphql-nested-filter-depth-limit

Conversation

@souvikghosh04

Copy link
Copy Markdown
Contributor

Summary

Bounds the relationship-nesting depth of GraphQL filter arguments (e.g. filter:{rel:{rel:{...}}}). Deeply nested filters expand into correlated EXISTS subqueries that the HotChocolate execution-depth rule does not cover, so a small deeply-nested request could amplify into a very expensive query.

Change

  • Thread a nesting-level counter through the recursive filter parser (GQLFilterParser.Parse / HandleNestedFilter* / ParseAndOr).
  • Reject filters whose relationship nesting exceeds runtime.graphql.depth-limit (when set and stricter) or a hardcoded safety ceiling (20) with an HTTP 400.
  • Backward compatible: the new Parse parameter is optional; external callers are unchanged.

Tests

  • Unit tests for the depth-limit resolution and the enforcement threshold, including the depth-limit = -1 (unlimited) case still capped at the ceiling.

Note

Filters nesting beyond 20 relationship levels now return 400 instead of executing; this is far above typical usage.

Thread a nesting-level counter through the recursive GraphQL filter parser and reject filters whose relationship nesting exceeds runtime.graphql.depth-limit (when set and stricter) or a hardcoded safety ceiling. Prevents nested-filter depth-bomb amplification into deeply correlated EXISTS subqueries, which the HotChocolate execution-depth rule does not cover.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a guardrail to the GraphQL filter parser to cap relationship-nesting depth in filter:{ rel:{ rel:{ ... }}} scenarios, preventing small requests from expanding into very expensive nested query plans.

Changes:

  • Introduces a maximum nested-filter depth (hard ceiling of 20) and enforces it during recursive filter parsing, optionally honoring a stricter runtime.graphql.depth-limit.
  • Threads a nestingLevel counter through recursive parsing paths (Parse, HandleNestedFilterForSql/Cosmos, ParseAndOr) and returns HTTP 400 on violations.
  • Adds unit tests validating effective limit selection and the enforcement helper.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Core/Models/GraphQLFilterParsers.cs Adds max-depth resolution/enforcement and propagates nesting depth through recursive parsing.
src/Service.Tests/UnitTests/GraphQLFilterParserUnitTests.cs Adds unit tests for depth-limit resolution and guard enforcement behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 89 to +91
List<ObjectFieldNode> fields,
BaseQueryStructure queryStructure)
BaseQueryStructure queryStructure,
int nestingLevel = 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants