Symfony's JsonPath Evaluates Attacker-Controlled Regular Expressions in match()/search() Without Limits — ReDoS
Description
Published to the GitHub Advisory Database
May 28, 2026
Reviewed
May 28, 2026
Last updated
May 28, 2026
Description
The
JsonPathcomponent'smatch()andsearch()filter functions compile a caller-supplied pattern straight intopreg_match():transformJsonPathRegex()only performs cosmetic escaping: there is no length cap, no restriction to the RFC 9485 i-regexp subset, and no bound on backtracking. An application that evaluates an attacker-influenced JSONPath expression server-side (e.g. one taken from a query parameter or API field and passed toJsonCrawler) can therefore be made to run a catastrophic-backtracking pattern such as$[?search(@, "(a+)+$")]. Evaluated against a moderately sized document, this pins a CPU core for seconds per request, so a handful of concurrent requests exhausts the worker pool: a denial of service. Because thepreg_match()calls are prefixed with@, the PCRE backtrack-limit errors that would otherwise surface are suppressed, leaving no log trace.Conditions for exploitation
An application that evaluates an attacker-influenced JSONPath expression containing a
match()/search()filter against any non-trivial JSON input.Resolution
JsonCrawlerruns thepreg_match()calls through a helper that lowerspcre.backtrack_limitto 10000 for the duration of the call (restoring the previous value afterwards), so a pathological pattern fails fast instead of stalling the worker.The patch for this issue is available here for branch 7.4.
Credits
Symfony would like to thank Himanshu Anand for reporting the issue and Alexandre Daubois for providing the fix.
References