fix(backend): expand saved search query length to 2048 and enforce AST node complexity guard (#2604) - #2653
Merged
Merged
Conversation
jcscottiii
force-pushed
the
fix-2604-saved-search-query-length
branch
from
July 28, 2026 18:36
a8fc771 to
2c55401
Compare
…T node complexity guard (#2604) Increases SavedSearch.query max length from 256 to 2048 characters in OpenAPI schemas and backend HTTP handlers (CreateSavedSearch and UpdateSavedSearch). To protect Cloud Spanner against parameter exhaustion and query amplification attacks while permitting long feature ID lists (issue #2604), this change introduces: 1. Upstream AST Deduplication (searchtypes.Deduplicate) based on the Boolean Idempotent Law (A AND A = A, A OR A = A). 2. Structural AST Complexity Validation capping post-deduplication AST complexity to MaxASTNodes = 50. 3. Recursive Saved Search Expansion Safeguard in ValidateQueryReferences ensuring nested saved: search expansion cannot exceed 50 AST nodes. 4. Comprehensive unit, HTTP handler boundary, Spanner emulator, and programmatic worst-case regression test suites. Fixes #2604
jcscottiii
force-pushed
the
fix-2604-saved-search-query-length
branch
from
July 28, 2026 21:19
2c55401 to
30e6952
Compare
neilv-g
approved these changes
Jul 29, 2026
Collaborator
Author
|
This can wait until next week's release @neilv-g |
github-merge-queue
Bot
removed this pull request from the merge queue due to no response for status checks
Aug 3, 2026
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR resolves Issue #2604 by expanding the
SavedSearch.querycharacter length limit from 256 to 2048 characters across OpenAPI schemas, Go HTTP backend validation handlers, and Lit frontend components.To permit users to bookmark long feature ID lists (e.g., 33+ feature IDs) while protecting Cloud Spanner against parameter exhaustion limits (950 max parameters) and query amplification attacks, this change introduces upstream AST deduplication and structural complexity validation.
What Was Changed
OpenAPI Schema Definitions (
openapi/backend/openapi.yaml):SavedSearch.querymaxLength: 2048(was 256).SavedSearchUpdateRequest.querymaxLength: 2048anddescriptionmaxLength: 1024.SavedSearchUpdateRequest.namemaxLength: 32.make openapi).Upstream Go Backend Validation (
backend/pkg/httpserver&lib/backendtypes):savedSearchQueryMaxLength = 2048.const MaxASTNodes = 50inlib/backendtypes/types.go.searchtypes.Deduplicate) and node complexity validation (CountNodes(dedupNode) <= 50) inCreateSavedSearchandUpdateSavedSearch.backendtypes.ErrQueryComplexityExceededto HTTP400 Bad Request.Spanner Adapter Expansion Safeguard (
lib/gcpspanner/spanneradapters):CountNodes(Deduplicate(expandedNode)) <= 50inValidateQueryReferencesafter recursive@saved-searchresolution to prevent expansion amplification bypasses.Frontend Constraints & Error Formatting (
frontend/src/static/js):QueryMaxLength: 2048andDescriptionMaxLength: 1024inwebstatus-saved-search-editor.ts.frontend/src/static/js/api/errors.tsto formatfieldErrorMapstrings directly for Toast notifications.Test Suite & Verification:
create_saved_search_test.goandupdate_saved_search_test.go.nilsafety unit tests infeatures_search_parse_test.go.TestWorstCaseMaxComplexityQuerySpannerLimitsinspanner_pipeline_analysis_test.goverifying that a worst-case 50-node query consumes only 27 / 950 parameters (2.84% of limit) and 5.7 KB / 1 MB SQL text (0.55% of limit).Corrected Assumptions / Learnings
AND/ORtrees from ANTLR, deduplicating children leaves single-childKeywordnodes(A). Unwrapping single-childKeywordnodes (if node.IsKeyword() && len(children) == 1 { return children[0] }) collapses binary tree chains like(((A AND A) AND A) AND A)down toA.expandSavedSearches(inValidateQueryReferences) to prevent nested@saved-searchreferences from amplifying AST node complexity post-validation.Fixes #2604