Symfony UX 2.36.0 is a security release for the 2.x branch: it fixes seven
vulnerabilities in the LiveComponent and Autocomplete packages, two of them
rated medium severity. If your application depends on
symfony/ux-live-component or symfony/ux-autocomplete, upgrade as soon
as possible. The same fixes are also available on the 3.x branch through
Symfony UX 3.1.0.
Medium severity
Two cross-site scripting issues are fixed in this release.
The Autocomplete Stimulus controller rendered AJAX response items by
interpolating the text field directly into the dropdown's HTML, so any
markup contained in the response was executed by the browser. When the
dropdown values came from user-supplied content, an attacker could craft a
string that triggered stored XSS for any other user who later opened a page
with an autocomplete widget backed by the same data. The remote-data
renderers now HTML-escape values by default. Endpoints that legitimately
return HTML, for example to highlight the search term, can opt back in with
the new options_as_html: true option
(CVE-2026-49216).
LiveComponent re-renders interpolated the child component tag name, taken
from client-controlled JSON, into the response without validation, allowing
arbitrary HTML, including <script> tags, to be injected on any re-render
of a component that contains at least one child. The default
Accept header gate made this mostly a defense-in-depth gap, but it became
directly exploitable on applications with a relaxed CORS policy. The child
tag is now validated against a strict HTML tag-name pattern and anything that
isn't a valid tag is dropped
(CVE-2026-49210).
Low severity
The LiveComponent endpoint gated #[LiveAction] invocations on the
Accept: application/vnd.live-component+html header as a CSRF measure, but
that header is CORS-safelisted and can be set by a cross-origin fetch()
without a preflight, so it offered no protection. The endpoint now also
requires X-Requested-With: XMLHttpRequest, which is not CORS-safelisted
and forces a preflight that fails for cross-origin attempts. The bundled
Stimulus client already sends this header, so standard usage is unaffected;
cross-origin callers must add it to their CORS allow-list
(CVE-2026-49215).
A #[LiveProp] typed as a date with no explicit format was hydrated
with the permissive DateTime constructor, which accepts relative strings
such as "now" or "+10 years". A client could push a writable date
prop to an arbitrary point in time and slip past time-based business checks.
Format-less date props are now parsed strictly as RFC 3339, matching the
format already emitted on the way out
(CVE-2026-49208).
The _batch controller issued a full sub-request for every entry in the
client-supplied actions array without bounding its size, so a single
request with thousands of actions could exhaust CPU, memory, and database
connections. The number of actions per batch is now capped at 50, and the
JavaScript client splits larger batches into multiple requests so legitimate
usage is unaffected
(CVE-2026-49209).
The HMAC protecting read-only LiveComponent props covered only the prop
key/value pairs, not the component name or the slot the props belong to. A
signed blob minted for one component was therefore a valid signature for
another component with matching prop names, and a props blob could be
replayed in the propsFromParent slot. The HMAC pre-image now includes the
component name and a slot identifier, so cross-component and cross-slot
replays no longer verify
(CVE-2026-49212).
The Autocomplete entity endpoint built its LIKE expression by wrapping
the query in %...% without escaping the SQL wildcards %, _ and
\. Since the endpoint is public by default and searches every property of
the entity, an unauthenticated user could send % to match every row or
use the endpoint as a blind boolean oracle against columns the application
never meant to expose. Those characters are now escaped and matched literally
through an explicit ESCAPE clause
(CVE-2026-49211).
Credits
We would like to thank Pascal Cescon, Anthropic (via Project Glasswing) and Alex Ashkov for reporting these issues, and Pascal Cescon and Hugo Alliaume for providing the fixes.
Full Changelog
- CVE-2026-49215 [LiveComponent] Require X-Requested-With header to prevent CSRF (@Kocal)
- CVE-2026-49216 [Autocomplete] Fix XSS via unescaped AJAX response data (@Kocal)
- CVE-2026-49208 [LiveComponent] Parse format-less date LiveProps strictly with RFC 3339 (@Kocal)
- CVE-2026-49209 [LiveComponent] Cap the number of actions per
_batchrequest (@Kocal) - CVE-2026-49210 [LiveComponent] Reject malicious child component tags (@Kocal)
- CVE-2026-49212 [LiveComponent] Bind HMAC checksum to component name and slot (@Kocal)
- CVE-2026-49211 [Autocomplete] Escape LIKE wildcards in the search query (@Amoifr)