6 min read
0%

CSRF

Back to Blog
CSRF

CSRF

CSRF works because browsers automatically attach ambient credentials like cookies when a user is already logged in. If the server cannot distinguish a real user action from a cross-site submission, the attack lands. Defenses are straightforward when the threat model is clear: verify origin, require an unguessable token, and reduce cookie reach with SameSite where it fits.

Minimal Example

app.post("/transfer", requireSession, verifyCsrf, async (req, res) => {
  assertOrigin(req.headers.origin, env.APP_ORIGIN);
  assertEqual(req.headers["x-csrf-token"], req.session.csrfToken);

  await moveFunds(req.body);
  res.sendStatus(204);
});

What It Solves

  • Separates user intent from the browser’s habit of sending cookies automatically.
  • Protects state-changing routes even when a user is actively signed in.
  • Combines well with SameSite cookies and origin checks for layered defense.

Failure Modes

  1. Relying on CORS alone even though simple form posts can still reach your endpoint.
  2. Protecting JSON APIs but forgetting old form endpoints or upload routes.
  3. Treating SameSite as a complete replacement for explicit CSRF verification.

Production Checklist

  • Require CSRF tokens or equivalent double-submit protection on state-changing browser routes.
  • Validate Origin or Referer on sensitive requests where possible.
  • Use SameSite cookies deliberately and verify the exact behavior your login flows require.

Closing

CSRF is not complicated once you model the browser correctly. The danger comes from forgetting that cookies travel even when intent does not.


Browser support snapshot

Live support matrix for same-site-cookie-attribute from Can I Use.

Show static fallback image Data on support for same-site-cookie-attribute across major browsers from caniuse.com

Source: caniuse.com

Canvas is not supported in your browser