Skip to content

Bound GraphQL nested-filter recursion depth - #3776

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

Bound GraphQL nested-filter recursion depth#3776
Souvik Ghosh (souvikghosh04) wants to merge 2 commits 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 thread src/Core/Models/GraphQLFilterParsers.cs Outdated
Address review feedback: keep the original 4-parameter public GQLFilterParser.Parse for binary compatibility and move the nesting-depth-tracking logic into a separate private 5-parameter overload used for recursion.
@souvikghosh04 Souvik Ghosh (souvikghosh04) moved this from In Progress to Review In Progress in Data API builder Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Review In Progress

Development

Successfully merging this pull request may close these issues.

4 participants