What is CSRF and how do you prevent it?
Cross-Site Request Forgery (CSRF) is an attack where a malicious site causes an authenticated user's browser to send a forged request to a target site. Because browsers automatically attach cookies to same-origin requests, the target server cannot distinguish a legitimate request from a forged one based on cookies alone.
The attack works as follows: a victim is logged into bank.com, which sets a session cookie. The attacker lures them to evil.com, which contains an image tag or hidden form that fires a POST to bank.com/transfer. The browser sends the request with the victim's cookie, and the server processes it as legitimate.
Primary defenses:
**Synchronizer Token Pattern (Anti-CSRF Token):** The server generates a unique, unpredictable token per session (or per form), embeds it in the HTML form or JavaScript-accessible meta tag, and validates it on every state-changing request. The attacker cannot read the token due to the same-origin policy, so they cannot forge a valid request. This is the gold standard. Frameworks like Django, Rails, and Spring include this by default.
**SameSite Cookie Attribute:** Setting `SameSite=Strict` or `SameSite=Lax` on session cookies instructs the browser not to send them on cross-site requests. `Strict` blocks all cross-site sends; `Lax` blocks POST but allows safe top-level navigations. This is now the browser default for cookies without an explicit attribute in modern browsers. It is a strong second layer but not a complete replacement for token-based protection in all legacy environments.
**Double Submit Cookie:** The server sets a random value as both a cookie and requires it as a request parameter. Since the attacker cannot read cookies cross-origin, they cannot replicate the value in the parameter. Useful for stateless architectures.
**Origin / Referer Header Validation:** Check that the `Origin` or `Referer` header matches the expected domain. Less reliable as headers can be absent (Referer is blocked by some privacy settings), so this should be a secondary check.
**Custom Request Header:** APIs that require a custom header (e.g., `X-Requested-With: XMLHttpRequest`) exploit the fact that simple cross-site requests cannot set arbitrary headers. SPAs using JSON APIs with custom headers are naturally protected. However, this only works when the server enforces the header check.
In modern stack terms: Django's `CsrfViewMiddleware` handles token injection and validation. For REST APIs consumed by SPAs, `SameSite=Lax` plus CORS restrictions usually suffices. Always combine layers.
Explains the attack mechanism and names at least one concrete prevention (tokens or SameSite), with correct reasoning about why it works.
Covers attack flow precisely, explains the synchronizer token pattern and SameSite cookies, discusses trade-offs between approaches, and mentions how modern frameworks implement this.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment