How it works
Browsers attach a site's cookies to requests sent to that site, even when a different site starts the request. If a bank changed a payee through a plain form post checked only by a session cookie, a malicious page could submit that form in the background and the bank would see a valid, signed-in request. The attacker never sees the response; the damage is the action itself.
Defences stack. Session cookies set to SameSite=Lax or Strict are left off most cross-site requests. A CSRF token, a random value tied to the session that must come back with every form or state-changing request, proves the request came from your own pages, and Django, Laravel and Rails check these tokens by default. Checking the Origin header helps too, and Next.js Server Actions accept only POST requests whose origin matches the host.
Actions that change data should never run on GET requests. APIs that authenticate with a token in the Authorization header rather than a cookie are not exposed to classic CSRF, because browsers do not add that header on their own. CORS is not a CSRF defence on its own: simple form posts are sent without asking, and CORS mainly controls who may read the response.
Cross-site request forgery (CSRF) vs the alternatives
Related terms
More in Security
Common attacks