Glossary
What is CSRF (Cross-Site Request Forgery): an attack that makes a logged-in user send requests they did not intend
CSRF (Cross-Site Request Forgery) uses a logged-in user's browser to send a request they never intended (a transfer, a settings change) via another site. How it works, and the main defense (CSRF tokens, SameSite cookies, Origin checks) — explained defensively, without attack steps.
CSRF is when simply opening another site while still logged in triggers a transfer or settings change without you knowing. Here's how it works and how to reliably prevent it (no attack steps).
Why it works (the mechanism)
A browser automatically attaches a site's cookies to requests for that site. So if a user is logged into their bank, a request to the bank triggered from a malicious page still carries "the user's cookies." To the server, it's indistinguishable from a legitimate action.
Where XSS "runs code in the victim's browser," CSRF "borrows the victim's logged-in state" (→ What is XSS).
Defense
Require a CSRF token
On state-changing actions (form submits, APIs), require an unguessable one-time token issued by the server; reject requests without it. Most frameworks ship this.
Set SameSite cookies
Mark session cookies SameSite=Lax (or Strict) so cookies aren't attached to cross-site-originated requests. Lax is the modern default and helps a lot on its own.
Don't use GET for state changes
GET (viewing) must have no side effects. Make changes POST/PUT/DELETE and run them through token validation.
Check Origin / Referer
For sensitive actions, verify the request's Origin is your own site and reject external origins.
This site's view: mostly 'solved', but don't get complacent
Framework CSRF tokens plus the browser's SameSite=Lax default have hugely reduced classic CSRF. Still, it happens in custom APIs, legacy setups, and admin panels that skipped the token. Even if you "leave it to the framework," verify once yourself that state-changing paths actually run token validation.
Common gaps
Even when you know the mechanism, implementations tend to slip in two places.
- GET with side effects: if a viewing GET changes state, an image tag or a plain link is enough for CSRF. Make state changes POST/PUT/DELETE and run them through token validation.
- Forgetting token validation on some paths: APIs and admin features added later often skip the token. Don't assume "the framework has it" — inventory every state-changing path once.
CSRF vs XSS vs SSRF
These three similar names can be told apart by who sends the request and what they rely on.
| Attack | Who sends the request | What is abused | Main defense |
|---|---|---|---|
| CSRF | The user's browser, without the user knowing | The browser attaching cookies automatically | CSRF tokens, SameSite cookies |
| XSS | The attacker's script running in the user's browser | Missing escaping when the page is rendered | Escaping on output, CSP |
| SSRF | Your server | A feature that fetches a URL it is given | Destination allowlist, blocking internal addresses |
CSRF and XSS both work through the user's browser. But if a page has XSS, a script inside it can read the CSRF token, so CSRF defenses are bypassed. CSRF protection assumes XSS is already handled.
A real example: a forged post treated as the user's own
In 2012, a threat to attack elementary schools was posted through the opinion form on the City of Yokohama's website. The owner of the PC it appeared to come from was arrested, and it later emerged that the arrest was a mistake. In December that year, Tokyo police explained, as reported by the Japanese press, that the post had been sent using CSRF: a visitor's browser was made to submit it after they opened a link posted on a message board.
Two lessons follow.
- A CSRF request looks exactly like the user's own: the server only sees the user's IP address and cookies. Logs alone cannot tell whether the user sent it or was made to send it.
- Forms without a login are in scope too: that opinion form needed no login. Put a token on any submission you would not want others to trigger (posts, applications, reports), whether or not it requires login.
CSRF is still a common weakness. In MITRE's "CWE Top 25" (the 25 most dangerous software weaknesses), published in December 2025, CSRF (CWE-352) ranked third.
How to check your own site
Set SameSite explicitly on session cookies
Check the session cookie's SameSite attribute in the browser's developer tools (Application → Cookies) or with the site audit. Chrome and Edge treat cookies without the attribute as Lax, but Safari and Firefox do not do this by default. Do not rely on browser defaults; set SameSite=Lax or Strict yourself.
Review CSRF exemptions
Check whether the framework's CSRF protection is switched off for some routes (Django's csrf_exempt, Laravel's exception list, Rails' skip_forgery_protection, and so on). Where there is a reason to switch it off, such as a webhook receiver, protect the route with signature verification instead.
Look for GET routes that change state
Go through your route list for GET routes that delete, update or log out. Move them to POST or similar and run them through token validation.
Add one more check to sensitive actions
For changing a password or email address, sending money or granting permissions, ask for the current password or multi-factor authentication on top of the token. Even if a request is forged, the user confirmation stops it.
Sources (primary)
- OWASP, "Cross-Site Request Forgery Prevention Cheat Sheet" — cheatsheetseries.owasp.org (tokens, Sec-Fetch-Site, limits of SameSite, XSS bypassing CSRF defenses, no state changes over GET)
- MITRE, "2025 CWE Top 25 Most Dangerous Software Weaknesses" (December 2025) — cwe.mitre.org (CWE-352 ranked third)
- web.dev, "SameSite cookies explained" — web.dev (which browsers treat cookies without the attribute as Lax)
- INTERNET Watch, report on the remote-control malware case (December 14, 2012, Japanese) — internet.watch.impress.co.jp (police explanation that CSRF was used for the Yokohama post)
- @IT, article on the wrongful arrests caused by impersonation malware and CSRF (November 2012, Japanese) — atmarkit.itmedia.co.jp
- IPA, "How to Secure Your Web Site" — ipa.go.jp (Japanese)
Read next
- Glossary: What is XSS · What is SSRF
- Basics: Security basics
Classification
CWE classifies the types of weakness behind vulnerabilities; MITRE ATT&CK classifies attacker techniques. Both are maintained by MITRE and widely used to label vulnerability reports and detection rules.
CWE (weakness type)
CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use
FAQ
QHow is CSRF different from XSS?
XSS runs a script in the victim's browser; CSRF uses the victim's logged-in state to send an unintended request. CSRF works even without running any script — just from the browser auto-sending cookies.
QWhat's the top defense against CSRF?
Require a CSRF token on state-changing requests (POST, etc.), and set SameSite (Lax/Strict) on session cookies. Most frameworks ship the token by default. Also: never use GET for state changes.
QIs SameSite alone enough?
It helps a lot but isn't complete on its own. Gaps remain on older browsers, certain navigations, and some subdomain setups — so pair it with CSRF tokens for defense in depth.
QDo forms that need no login still need CSRF protection?
Sometimes, yes. Even a contact or posting form can be submitted from another site through a visitor's browser, and the server then records that visitor's IP address as the sender. In Japan in 2012, a threat posted to the City of Yokohama's website had been sent via CSRF, and the owner of the PC it appeared to come from was wrongly arrested. Put a token on any form you would not want others to submit on a visitor's behalf, whether or not it needs a login.
QDo JSON APIs that authenticate with Bearer tokens need CSRF protection?
It depends on whether authentication uses cookies. CSRF relies on the browser attaching cookies automatically. An API that only accepts credentials the app adds itself, such as a Bearer token in the Authorization header, is generally not exposed to CSRF, because another site cannot make the browser add it. If the API authenticates with cookies, it needs tokens or an Origin check.
QWhat is Sec-Fetch-Site, and can it stop CSRF?
It is a request header the browser adds to say whether a request came from the same origin or site (same-origin / same-site) or from another site (cross-site). The OWASP CSRF guide lists rejecting cross-site state-changing requests based on it as one defense. Older browsers do not send it, so keep an Origin check as a fallback.