The Problem
As enterprise applications expand, search and filtering requirements rapidly become a major source of bugs and security vulnerabilities:
- Ad-Hoc String Concatenation: Engineering teams often piece together SQL or Elasticsearch criteria using string concatenation and arbitrary request parameters, opening severe injection attack vectors.
- Inconsistent Filtering Behavior: Different microservices implement pagination, sorting, and comparison operators (e.g.,
status:ACTIVE and price < 500) with conflicting syntaxes, causing poor client ergonomics. - Forgotten Tenant Scope Constraints: In multi-tenant platforms, relying on developers to manually attach
and tenant_id = ?to every query is a recipe for catastrophic data leaks.
The Architecture & Solution
To solve this across an enterprise platform, I designed Spring Search DSL—a three-stage compilation pipeline that makes search queries safe by construction:
User Query String → Lexer / Tokenizer → Recursive-Descent Parser → Abstract Syntax Tree (AST) → Semantic Validator & Field Whitelist → Backend Compilers (SQL / Elasticsearch)
Key Technical Capabilities:
- Deterministic Recursive-Descent Parser: Hand-written in Java 17 without heavy external parser generators (like ANTLR) to minimize dependency bloat and guarantee zero-overhead execution.
- Strict Field Whitelisting: Every field referenced in the query is validated against an explicit entity schema. Unauthorized or internal fields are rejected at the parsing stage.
- Mandatory Tenant Scoping: The tenant predicate is automatically injected into the generated AST root node during compilation, eliminating any possibility of cross-tenant data leakage.
- Pluggable Backend Compilers: Emits parameterized Spring Data
Specificationpredicates for relational databases or structured JSON query bodies for Elasticsearch clusters.
Engineering Challenges & Security Hardening
- Preventing Denial-of-Service (DoS) via Complex Nesting: Adversarial users could pass deeply nested parenthetical queries (e.g.,
((((a=1 AND b=2)...))))) to cause call-stack exhaustion. I implemented recursive depth caps and token length limits directly in the lexer stage to reject hostile inputs before AST construction. - Zero-Dependency Ergonomics: Engineered the library to integrate seamlessly with standard Spring Boot applications using intuitive annotations (
@SearchSpec) on controller endpoints.
Real-World Outcomes & Impact
- Zero Injection Vulnerabilities: 100% parameterization guarantee across all query endpoints in production.
- Hundreds of Lines of Code Removed: Replaced fragile, repetitive boilerplate across 40+ microservice endpoints with a single unified search annotation.
- Consistent Developer Experience: Standardized search syntax and response pagination across all internal and public API endpoints.