How CSRF attacks work: forging requests with victim's cookies
CSRF mechanics, same-site cookie attribute, SameSite=Strict, SameSite=Lax, CSRF tokens, idempotent GET requests, state-changing requests
Cross-Site Request Forgery (CSRF)
CSRF tricks a logged-in user's browser into making an authenticated request to your API from an attacker-controlled page. The browser automatically attaches cookies, so the request looks legitimate to your server.
The Attack
An attacker hosts a page at evil.com with a hidden form targeting yourbank.com/transfer. When a victim (who is logged in to yourbank.com) visits evil.com, JavaScript auto-submits the form. The browser sends the request including the victim's session cookie. The bank cannot distinguish it from a real transfer.
SameSite Cookie Attribute
// Set your session cookie with SameSite
res.cookie('session', token, {
httpOnly: true,
secure: true,
sameSite: 'Strict' // Cookie not sent on any cross-site request
// OR:
sameSite: 'Lax' // Cookie sent on top-level navigation (GET), not POST
});
Strict: The cookie is never sent on cross-site requests, even when the user navigates to your site from a link. Best security, may hurt UX for OAuth flows.
Lax (default in modern browsers): Cookie sent on top-level GET navigation but not on cross-site POST. This is why you should never perform state-changing actions on GET endpoints.
CSRF Still Matters
SameSite=Lax is now the browser default but is not a complete defense. Older browsers, some proxies, and certain subdomain scenarios can bypass it. For sensitive actions (payments, password changes), use CSRF tokens as an additional layer.
