CSRF Isn't Dead: The Edge Cases Still Shipping in 2026
Cybersecurity
SameSite=Lax by default in 2024 killed most classic CSRF. The remaining attack surface is narrower but real: same-site bypasses, JSON CSRF via fetch, and action endpoints that ignore Origin.
By Arjun Raghavan, Security & Systems Lead, BIPI · September 16, 2024 · 7 min read
I had this exact conversation with a senior engineer in March: 'CSRF? We don't worry about that anymore. SameSite is Lax by default.' Two weeks later we found a CSRF in their account-settings endpoint that worked from any subdomain on their primary domain because SameSite=Lax doesn't isolate by subdomain.
An attacker who got XSS on app.example.com could trigger state changes on api.example.com without any origin check, because both are same-site. Their main XSS defence was strong CSP on app.example.com, but the marketing subdomain ran a third-party CMS with no CSP at all. CSRF survived because the assumption that 'SameSite handles it' was wrong in their topology.
What SameSite=Lax actually protects
Lax blocks cookies on cross-site POST, PUT, DELETE, and PATCH. It allows them on top-level GET navigations (so links from external sites to your dashboard still log you in). It does not block same-site requests, where 'site' is defined as eTLD+1.
If your auth subdomain is auth.example.com and your API is api.example.com, Lax considers them same-site. Any XSS or HTML injection on any subdomain becomes a CSRF launchpad against the API. SameSite=Strict would isolate them at the cookie level (mostly), but Strict breaks too many flows for most teams.
JSON CSRF via fetch
Classic CSRF used HTML forms because forms could submit cross-origin without a preflight. JSON APIs were considered safe because content-type: application/json triggered a CORS preflight, which the browser would block on a cross-origin request without ACAO.
But fetch() with a simple body works around this. If your API accepts JSON-shaped data with content-type: text/plain (some do, lazy parsing), no preflight is sent. The cross-origin POST goes through with cookies attached. The response isn't readable, but the side effect (account update, password change, money transfer) already happened.
- APIs that accept text/plain or no content-type and JSON-parse the body
- APIs that accept multipart/form-data with JSON in a field
- GraphQL endpoints accessed via GET (some implementations support query in URL)
- JSONP endpoints that accept callback names from query params
Action endpoints that change state on GET
RFC says GET should be safe. Production says any developer who's tired might wire up DELETE-by-GET. We found an admin tool last year where /admin/delete-user?id=123 was a GET request because the original implementation came from a 'click the link in the email' flow and grew from there. Lax cookies allow GET; the endpoint was world-CSRF-able from any external site.
Auditing for this is mechanical. Walk every route in your routing config. Any GET handler that mutates state is a CSRF candidate. Convert to POST or DELETE with an explicit anti-CSRF check.
Defence in depth still applies
SameSite cookies are a baseline, not a complete defence. Layer Origin header validation, anti-CSRF tokens for sensitive operations (password change, email change, MFA enrolment), re-authentication for high-impact actions, and a security headers review that includes CSP frame-ancestors to block being framed.
For APIs that are consumed only by your own SPA, custom request headers (X-Requested-With or similar) are a cheap CSRF defence: cross-origin requests without preflight can't add custom headers, so the server rejects them. The header gets set by your fetch wrapper and validated server-side.
What still triggers CSRF reports
- Subdomain takeover or XSS on a sibling subdomain bypasses SameSite
- Endpoints accepting state changes on simple content-types (text/plain CSRF)
- GET handlers that mutate state without explicit token check
- OAuth callback endpoints that don't validate state parameter
- WebSocket upgrade endpoints that authenticate via cookie alone
CSRF reports in 2026 are narrower and more specific than 2018. The defence patterns are well-known. The bugs we still find come from teams who treat SameSite as a complete solution and stop thinking about the threat model. It isn't. Keep thinking.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.