Cross-Site Request Forgery (CSRF)
How attackers trick browsers into unwanted actions and how to block it
Overview
Cross-Site Request Forgery (CSRF) tricks a logged-in user's browser into sending an unwanted request to your site, such as changing their email or transferring money. It works because browsers automatically attach cookies to requests, even those triggered from a malicious page. The fix is to require proof that the request came from your own app, using tokens and cookie flags.
Syntax / Usage
Issue an unpredictable CSRF token, embed it in forms, and verify it on state-changing requests. Because attackers cannot read your token, they cannot forge valid requests.
// Server: generate and verify a per-session token
app.get("/form", (req, res) => {
const token = createCsrfToken(req.session);
res.render("form", { csrfToken: token });
});
app.post("/transfer", (req, res) => {
if (!verifyCsrfToken(req.session, req.body._csrf)) {
return res.status(403).send("Invalid CSRF token");
}
// Safe to perform the action
});
Examples
Include the token as a hidden field in every state-changing form:
POST /transfer HTTP/1.1
Content-Type: application/x-www-form-urlencoded
amount=100&to=alice&_csrf=8f3b2c9e1a...
Set SameSite on session cookies so they are not sent on cross-site requests:
res.cookie("session", token, { httpOnly: true, secure: true, sameSite: "strict" });
Common Mistakes
- Assuming a login check alone protects state-changing endpoints
- Performing writes on GET requests, which are easy to trigger remotely
- Omitting
SameSitecookie attributes - Reusing or exposing CSRF tokens so attackers can predict them
- Forgetting CSRF protection on APIs that rely on cookie-based sessions
See Also
web-security-authentication web-security-xss web-security-cors