What is CSRF (Cross-Site Request Forgery)?
Definition
CSRF (Cross-Site Request Forgery) is an attack in which another website causes a user's browser to send a state-changing request to a site where that user is logged in, without the user's knowledge. Because the browser attaches cookies automatically, the server may treat the request as genuine. The main defences are the SameSite cookie attribute, anti-CSRF tokens and verifying where a request came from.
Also known as: Cross-Site Request Forgery, XSRF, CSRF token, session riding, one-click attack

Ambient credentials are the root cause
After you sign in, the browser stores a session cookie and adds it to every request to that site on its own. CSRF exploits exactly that. When the user opens a malicious or compromised page in another tab, that page can make the user's browser submit a form to the target site. The request comes from the user's browser and carries a valid cookie, so without an extra check the server cannot tell it apart from something the user did deliberately.
The attacker never sees the response. CSRF is about making the victim perform an action, not about reading data: changing the account email, adding an administrator, placing an order or flipping a setting.
Which endpoints are exposed
- State-changing requests authenticated by cookies. This is where the real risk lives.
- GET requests that change state. A link like
/account/delete?id=5can be fired by something as small as an image tag. GET should only ever read. - The login form. In login CSRF, the victim is silently signed in to the attacker's account and their subsequent activity is recorded there.
APIs that authenticate with a token in the Authorization header are largely outside this class, because browsers never attach that header to a cross-site request on their own. Store the same token in a cookie and the exposure returns.
Defence in layers
| Control | How it works | Limitation |
|---|---|---|
| Anti-CSRF token | The server issues an unpredictable value tied to the session; requests whose form field or custom header lacks it are rejected | The primary defence when done right; an XSS flaw can still read it |
| SameSite cookie attribute | Cookies marked Lax or Strict are not sent on cross-site POST requests | Does not help against sibling subdomains that count as the same site; not sufficient alone |
| Origin and Fetch Metadata checks | The server inspects Origin or Sec-Fetch-Site and rejects cross-site state-changing requests | Headers can be missing on older clients, so a fallback rule is needed |
Set-Cookie: session=…; Secure; HttpOnly; SameSite=Lax
<form method="post" action="/account/email">
<input type="hidden" name="csrf_token" value="(random value bound to the session)">
<input type="email" name="new_email">
<button>Save</button>
</form>Frameworks such as Django, Rails and Laravel ship token protection out of the box. The most common failure is switching it off for one endpoint when an integration misbehaves and never switching it back on. OWASP's CSRF prevention cheat sheet treats SameSite as defence in depth rather than a replacement for a proper CSRF defence.
Misconceptions that leave gaps
- "We configured CORS, so CSRF is handled." CORS controls who can read responses; a plain form submission still reaches the server and is processed.
- "HttpOnly cookies stop CSRF." HttpOnly only hides the cookie from JavaScript. The browser still attaches it to requests.
- Putting the token in the URL. Query-string tokens end up in server logs and browser history.
- Treating XSS as unrelated. With an XSS flaw on the site, injected script can read the token and send the request itself, so CSRF defences offer no protection against it.

