Affected versions

Symfony JSON Path versions >=7.3.0, <7.4.23, >=8.0.0, <8.1.11 are affected by this security issue.

The issue has been fixed in Symfony JSON Path 7.4.23, 8.1.11.

Description

The fix for CVE-2026-45756 lowers pcre.backtrack_limit to 10000 around each preg_match() call of the match() and search() filter functions. That limit applies to one starting position, not to one call. PCRE resets its counter at every position it tries a match from. So an unanchored pattern that stays just under the limit is paid once per byte of the subject. Each call also starts from a fresh limit, so chaining clauses in one filter multiplies the work.

Two other paths made the cost of a query grow faster than its size, without any regular expression:

  • The filter evaluator scanned the whole expression for logical operators once per node. Its cost grew with the square of the number of chained clauses.
  • Queries starting with $ inside a filter, like @.x == $.limit or length($.items), were evaluated again for every node the filter visits.

An application that evaluates an attacker-influenced JSONPath expression can therefore still be made to hold a PHP worker. A document of 2 MB and a query of 2.5 KB take 3.5 minutes of CPU.

Resolution

JsonCrawler::find() now bounds the total regex work of one call, and throws an exception when that budget is exhausted. Filter expressions are parsed once per query, and absolute queries inside filters are evaluated once per query.

The patches for this issue are available here, here and here for branch 7.4 (and forward-ported to 8.1 and 8.2).

Credits

We would like to thank Kamil Vavra for reporting the issue and Nicolas Grekas for finding the related ones and providing the fix.