Script Valley
Web Security Fundamentals for Developers
Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF)Lesson 3.3

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 attack flow diagram

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.

Up next

Implementing CSRF tokens with the double-submit cookie pattern

Sign in to track progress