Severity by source
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Network-delivered CSRF requiring active victim interaction (UI:R, PR:N); integrity-only impact since LiveActions mutate state without inherent data exfiltration.
Primary rating from Vendor (https://github.com/symfony/ux).
CVSS VectorVendor: https://github.com/symfony/ux
Lifecycle Timeline
3DescriptionCVE.org
Description
When using symfony/ux-live-component, methods annotated with #[LiveAction] are invokable from the browser and mutate server-side state via AJAX. Symfony\UX\LiveComponent\EventListener\LiveComponentSubscriber::isLiveComponentRequest() gated these invocations on the presence of Accept: application/vnd.live-component+html, with a code comment stating that this acted as a CSRF protection.
The Accept header is a CORS-safelisted request header, so a cross-origin fetch() can set it without triggering a preflight. The header therefore provided no CSRF protection. Any #[LiveAction] could be forged cross-origin against a victim's session.
In practice the attack is mitigated by SameSite=Lax session cookies (Symfony's default), but applications using SameSite=None, credentials: 'include' with a permissive cookie policy, or that have been pivoted from another same-origin vector remained exposed.
Resolution
isLiveComponentRequest() now additionally requires the request header X-Requested-With: XMLHttpRequest. This header is not CORS-safelisted, so the browser issues a preflight OPTIONS request for any cross-origin attempt; Symfony does not advertise CORS for LiveComponent endpoints, the preflight fails, and the real request is blocked before it reaches the application. The bundled Stimulus client already sends X-Requested-With on every LiveComponent request (RequestBuilder.ts), so standard usage is unaffected. Cross-origin callers must add X-Requested-With to their CORS Access-Control-Allow-Headers allow-list.
The patch for this issue is available here for branch 2.x (and forward-ported to 3.x).
Credits
Symfony would like to thank Anthropic (via Project Glasswing) for reporting the issue and Hugo Alliaume for providing the fix.
AnalysisAI
CSRF protection bypass in symfony/ux-live-component allowed cross-origin invocation of any server-side #[LiveAction] method against an authenticated victim's session. The library incorrectly relied on the Accept: application/vnd.live-component+html header as a CSRF guard, but per the Fetch specification §3.2.2 this is a CORS-safelisted header, meaning cross-origin fetch() calls can include it without triggering a preflight OPTIONS request. Applications using SameSite=None cookies or those reachable via a same-origin pivot (e.g., XSS on the same domain) are genuinely exposed; Symfony's default SameSite=Lax policy substantially mitigates the risk for standard deployments. No public exploit has been identified and this vulnerability is not listed in the CISA KEV catalog.
Technical ContextAI
symfony/ux-live-component (pkg:composer/symfony/ux-live-component) is a Symfony UX package that implements reactive, AJAX-driven server-side components using a Stimulus JavaScript controller. Methods on component classes annotated with #[LiveAction] are invokable from the browser via AJAX, mutating server-side state. The LiveComponentSubscriber::isLiveComponentRequest() method in src/LiveComponent/src/EventListener/LiveComponentSubscriber.php gated these invocations on the presence of a custom Accept header value (application/vnd.live-component+html), with a code comment explicitly describing this as CSRF protection. The flaw (CWE-352, Cross-Site Request Forgery) is a design error: the Fetch specification lists Accept as a CORS-safelisted request header, which means a browser will dispatch a cross-origin fetch() containing that header without first issuing a preflight OPTIONS request. Without a preflight, the browser attaches the victim's session cookies, and the server sees a structurally valid LiveComponent request from an arbitrary origin. The fix adds a mandatory check for X-Requested-With: XMLHttpRequest, a non-safelisted header that forces a preflight for any cross-origin caller; since Symfony does not advertise CORS for LiveComponent endpoints the preflight fails, blocking the forged request before it reaches application logic.
RemediationAI
Upgrade symfony/ux-live-component to version 2.36.0 (for 2.x installations) or 3.1.0 (for 3.x installations). These versions add a mandatory X-Requested-With: XMLHttpRequest header check in isLiveComponentRequest(); the bundled Stimulus controller (RequestBuilder.ts) already sends this header on every LiveComponent request, so standard usage requires no client-side changes. The patch commit is available at https://github.com/symfony/ux/commit/aed7493db2b4b7bf1f9c79b33cda544f06904b27. If immediate upgrade is not possible, the most effective compensating control is to confirm session cookies are configured with SameSite=Lax (Symfony's default) - this blocks the majority of cross-origin CSRF paths at the browser layer, though it does not protect against same-origin pivots such as stored XSS. Applications that require SameSite=None for cross-site embedding should treat upgrade as urgent. Note a minor breaking change: any custom cross-origin callers of LiveComponent endpoints must add X-Requested-With to their CORS Access-Control-Allow-Headers allow-list or their requests will begin failing preflight checks after the upgrade. The GitHub Security Advisory is at https://github.com/symfony/ux/security/advisories/GHSA-4m4j-hmqq-3gxm.
Same weakness CWE-352 – Cross-Site Request Forgery (CSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-45218
GHSA-4m4j-hmqq-3gxm