SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration
SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration

Cross-Site Request Forgery (CSRF) tricks an authenticated user's browser into sending unwanted requests to your application — transferring funds, changing email addresses, or deleting data — all without the user's knowledge. This guide is for developers, technical leads, and security-conscious owners who want to audit and harden their web applications against CSRF today. Work through each step in order, and by the end you will have layered, robust CSRF defences in place.

01

Understand the CSRF Threat Model

Before writing a single line of defence code, map out exactly where your application is exposed. CSRF only affects state-changing operations (anything that modifies data or triggers an action), and only when the victim is already authenticated. Read-only GET requests are generally safe, but every POST, PUT, PATCH, and DELETE endpoint that relies on cookie-based authentication is a potential target.

  • List every endpoint that changes state: form submissions, account updates, payments, deletions, and admin actions.
  • Confirm which endpoints rely on session cookies or other automatically-sent credentials for authentication.
  • Mark endpoints that accept cross-origin requests via CORS — these need careful scrutiny.
  • Document endpoints exposed to third-party integrations or webhooks, as these often require special handling.
  • Check whether your application framework has built-in CSRF middleware and whether it is currently enabled.
02

Implement the Synchronizer Token Pattern

The synchronizer token pattern is the gold-standard CSRF defence. The server generates a secret, unpredictable token tied to the user's session, embeds it in every HTML form as a hidden field, and then validates it on every incoming state-changing request. An attacker on a different origin cannot read or forge this token.

  • Generate a cryptographically random token (at least 128 bits of entropy) per session, or per request for high-security flows.
  • Store the token server-side in the user's session — never trust a token sent only from the client.
  • Embed the token in every HTML form as a hidden input: <input type="hidden" name="_csrf" value="{token}">.
  • For AJAX requests, read the token from a meta tag or a cookie and send it in a custom request header (e.g. X-CSRF-Token).
  • On the server, reject any state-changing request where the submitted token does not match the session token — return HTTP 403.
  • Rotate the CSRF token after privilege-level changes (e.g. login, role change).
  • Use your framework's built-in CSRF protection if available (Django's {% csrf_token %}, Laravel's , Rails' protect_from_forgery, Spring Security's CSRF filter, etc.) rather than rolling your own.
03

Configure the SameSite Cookie Attribute

The SameSite cookie attribute instructs browsers not to send cookies with cross-site requests, providing a powerful second layer of CSRF defence that requires no server-side token validation. It is supported by all modern browsers and should be set on every session and authentication cookie.

  • Set SameSite=Strict on session cookies where you do not need cross-site navigation to carry the session (e.g. banking dashboards, admin panels).
  • Set SameSite=Lax as a minimum on all other session cookies — this blocks CSRF from cross-site POST requests while still allowing top-level GET navigations.
  • Never use SameSite=None unless the cookie genuinely needs to be sent cross-site (e.g. embedded widgets); always pair it with Secure.
  • Set the Secure flag on all cookies so they are only sent over HTTPS.
  • Set the HttpOnly flag to prevent JavaScript from reading session cookies, reducing XSS-to-CSRF pivot attacks.
  • Audit your Set-Cookie headers using browser DevTools or an automated scanner — Sensagraph checks cookie security attributes across your site automatically.
04

Verify Origin and Referer Headers

Checking the Origin and Referer request headers is a lightweight, stateless server-side check that can stop many CSRF attacks even before token validation. Browsers attach these headers to cross-site requests, and legitimate same-site requests from your own frontend will carry your domain in them.

  • On state-changing requests, read the Origin header. If it is present and does not match your allowed origin(s), reject the request with HTTP 403.
  • If Origin is absent, fall back to checking the Referer header and verify it starts with your application's base URL.
  • Reject requests where both Origin and Referer are absent and the request is not from a known safe context (some strict security postures reject them outright).
  • Maintain an explicit whitelist of allowed origins — do not use substring or suffix matching, which can be bypassed (e.g. evil.yourdomain.com).
  • Do not rely solely on Referer checking — it can be suppressed by privacy tools and HTTPS-to-HTTP transitions.
05

Use the Double Submit Cookie Pattern as a Fallback

When synchronizer tokens are impractical — for example, in stateless architectures or distributed systems without centralised session stores — the double submit cookie pattern provides a usable alternative. A random value is stored both as a cookie and as a request parameter; the server checks they match.

  • Generate a cryptographically random value and set it as a cookie (not HttpOnly, so JavaScript can read it).
  • Include the same value in every state-changing request as a hidden form field or custom header.
  • On the server, verify the cookie value and the submitted value match — a cross-origin attacker cannot read the cookie due to the Same-Origin Policy.
  • Prefer the signed double submit cookie variant: HMAC-sign the token with a server-side secret so an attacker cannot craft a matching pair even if they can set cookies for a parent domain.
  • Never use this pattern if your application is vulnerable to subdomain takeover, as an attacker controlling a subdomain could set cookies on the parent domain.
06

Protect API Endpoints

REST and GraphQL APIs are commonly assumed to be CSRF-safe because they use JSON, but they are still vulnerable if they accept cookies and do not enforce proper content type or token checks. Attackers can use HTML forms or fetch requests to trigger state changes on APIs that lack proper protection.

  • Require Content-Type: application/json on all JSON API endpoints — HTML forms cannot send this content type, blocking simple CSRF vectors.
  • Apply CSRF token validation to all cookie-authenticated API endpoints, just as you would for HTML forms.
  • For APIs that use Authorization headers (Bearer tokens, API keys) instead of cookies, CSRF is not applicable — confirm your API clients are not also sending session cookies.
  • Review CORS policy: only allow trusted origins in Access-Control-Allow-Origin and never use * with Access-Control-Allow-Credentials: true.
  • Avoid accepting credentials in URL parameters (e.g. ?token=...) as these are logged in server logs and browser history.
  • If using GraphQL, apply CSRF tokens at the HTTP transport level, not within the GraphQL layer, since mutations are semantically state-changing.
07

Harden Session Management

CSRF attacks exploit the trust a server places in an authenticated session. Tightening your session management reduces the window and blast radius of a successful CSRF attempt.

  • Regenerate session IDs after login, role changes, and privilege escalation to prevent session fixation attacks that precede CSRF.
  • Set session cookie expiry to the shortest practical period — use idle timeouts (e.g. 15–30 minutes of inactivity) in addition to absolute timeouts.
  • Scope session cookies to the narrowest path and domain necessary: use the Path=/ attribute only if your application genuinely needs it across all paths.
  • Implement a logout endpoint that fully invalidates the server-side session, not just clears the client-side cookie.
  • Consider requiring re-authentication (step-up auth) for high-risk actions such as changing email, password, or payment details — even a valid CSRF token cannot help an attacker who needs fresh credentials.
  • Log and alert on sudden surges in CSRF token validation failures, which may indicate an active attack campaign.
08

Test and Continuously Monitor

CSRF defences can silently break during framework upgrades, refactoring, or new feature development. Continuous testing ensures your protections remain effective over time.

  • Manually test each state-changing endpoint by crafting a cross-origin HTML form or fetch request without a valid CSRF token — the server should return HTTP 403.
  • Include CSRF token validation tests in your automated test suite (unit and integration tests) so regressions are caught in CI/CD pipelines.
  • Conduct periodic penetration tests with a focus on CSRF, particularly after major releases or architectural changes.
  • Review third-party libraries and frameworks for CSRF-related CVEs and apply patches promptly.
  • Use automated scanning to continuously check for missing or misconfigured CSRF protections across all your web properties — Sensagraph detects common CSRF misconfigurations as part of its continuous scanning.
  • Review your Content Security Policy (CSP) headers — a strong CSP that disallows inline scripts reduces the risk of XSS-assisted CSRF bypasses.
  • Subscribe to security advisories for your tech stack (e.g. Django, Laravel, Spring) to stay ahead of CSRF-related vulnerability disclosures.

Frequently asked questions

Cross-Site Request Forgery (CSRF) is an attack where a malicious website tricks an authenticated user's browser into sending a forged request to your application. Because the browser automatically includes session cookies, the server cannot distinguish the forged request from a legitimate one. This can lead to unauthorized actions such as changing account details, transferring funds, or deleting data — all without the user's knowledge.

No. HTTPS encrypts data in transit but does not prevent CSRF, because the attack does not intercept traffic — it abuses the browser's automatic cookie-sending behaviour. HTTPS is still essential for overall security, but you must implement explicit CSRF defences such as tokens and the SameSite cookie attribute.

SameSite=Lax blocks CSRF attacks via cross-site POST, PUT, PATCH, and DELETE requests, which covers the vast majority of CSRF vectors. However, it does not protect top-level GET navigations that trigger state changes (which you should avoid by design) and may not be honoured by older browsers. You should use SameSite cookies together with CSRF tokens for defence in depth.

Yes, if your API uses cookie-based authentication. Although browsers cannot send JSON via a standard HTML form, they can initiate cross-site fetch requests that carry cookies. If your API does not validate CSRF tokens or enforce strict Content-Type checking, it may still be vulnerable. APIs that use only Authorization headers (Bearer tokens) and never cookies are generally not vulnerable to CSRF.

At a minimum, generate a new CSRF token per user session and rotate it after login or privilege changes. For very high-security operations (e.g. financial transactions), consider per-request tokens. Per-request rotation provides stronger security but can cause usability issues with browser back buttons and multiple open tabs, so weigh the trade-off for your application.

Yes. Sensagraph's continuous automated scanning checks for common CSRF misconfigurations, including missing CSRF tokens on forms, incorrect SameSite cookie settings, and misconfigured CORS policies that could enable CSRF exploitation.