Intermediate·18 min read·Updated 2026-10-15

Cross-Site Request Forgery (CSRF): SameSite Cookies & Anti-CSRF Token Defense

Original WeSecureX guide for authorized testing of sites you own. Linked Sources are citations for verification - not copied articles. Ads are not served on this page.

Cross-Site Request Forgery (CSRF, CWE-352) is an attack where a malicious third-party website tricks an authenticated user's browser into executing unwanted actions on a trusted web application. Because browsers automatically attach ambient credentials (such as session cookies and HTTP Basic Auth headers) to cross-origin requests, the target server cannot distinguish between legitimate user actions and forged cross-site requests. While modern browser support for `SameSite=Lax` cookies has reduced baseline CSRF exposure, top-level navigation, legacy browsers, and API endpoints using GET requests for state changes remain vulnerable. This guide details defense-in-depth CSRF prevention, comparing `SameSite` flags, Synchronizer Token Patterns, and Double-Submit Cookie schemes. Verify your cookie security headers with the [WeSecureX Security Headers Checker](/tools/security-headers-checker) and [CORS Checker](/tools/cors-checker).

Quick Answer

Mitigate CSRF by setting SameSite=Strict or SameSite=Lax on all session cookies, requiring unique cryptographic anti-CSRF tokens in request headers for state-changing HTTP requests (POST, PUT, DELETE), and validating Fetch Metadata request headers (Sec-Fetch-Site).

Key Takeaways
  • CSRF exploits ambient browser credentials (cookies) to execute forged state changes.
  • SameSite=Lax blocks cookies on cross-origin POST requests, offering strong baseline protection.
  • Synchronizer token patterns and custom headers (e.g., X-CSRF-Token) prevent cross-origin script forgery.
  • Fetch Metadata (Sec-Fetch-Site) provides modern, native server-side origin validation.
Visual Diagram · Cross-Site Request Forgery Attack vs. Anti-CSRF Token Validation
1

1. Authenticated User Session

User logs into bank.com; browser receives session cookie without SameSite=Strict.

2

2. Visiting Malicious Origin

User visits evil.com, which executes a hidden auto-submitting form targeting bank.com/transfer.

3

3. Ambient Cookie Attachment

Browser automatically attaches bank.com session cookies to the forged request.

4

4. Token / SameSite Block

Target server rejects request because the unique X-CSRF-Token header is absent.

ShareShare on XLinkedIn

1. Understanding CSRF Mechanics & Ambient Cookie Vulnerabilities

WeSecureX Security Headers Checker analyzing SameSite and Cookie Security Flags
WeSecureX Security Headers Checker analyzing SameSite and Cookie Security FlagsWeSecureX Platform View

CSRF exploits the fundamental browser trust model: whenever a client browser submits an HTTP request to https://example.com, any cookies stored for example.com are attached automatically in the Cookie: header, regardless of where the request originated.

Consider an online banking application where transferring funds is handled via a standard form submission. If an authenticated user visits a malicious website while their banking session is active, the attacker's page can automatically submit a hidden form to https://bank.example.com/api/transfer. The victim's browser faithfully attaches the authenticated session cookie, and the server processes the fraudulent financial transaction as if it were legitimately requested by the victim.

Traditional defenses that rely solely on origin checking or CAPTCHAs can disrupt legitimate user workflows if misconfigured. Modern web security requires enforcing strict cookie flags combined with anti-CSRF tokens. Learn how to audit your web application's cookie attributes and response headers using the WeSecureX Security Headers Checker and review our guide on Why Security Headers Are Your First Line of Defense.

html
<!-- Malicious CSRF Payload hosted on third-party website (evil.com) -->
<form action="https://bank.example.com/api/transfer" method="POST" id="csrfForm">
  <input type="hidden" name="recipient" value="attacker_account_9981" />
  <input type="hidden" name="amount" value="5000" />
</form>
<script>
  // Silently submits cross-origin POST request when victim opens the page
  document.getElementById('csrfForm').submit();
</script>

3. Cryptographic Token Implementations: Synchronizer & Fetch Metadata

WeSecureX Security Tools Directory showing Security Checkers and Scanner Utilities
WeSecureX Security Tools Directory showing Security Checkers and Scanner UtilitiesWeSecureX Platform View

While SameSite=Lax provides baseline protection, defense-in-depth requires cryptographic anti-CSRF tokens for all state-changing endpoints (POST, PUT, PATCH, DELETE). In the Synchronizer Token Pattern, the server generates a cryptographically random, unpredictable token tied to the user's current session and embeds it in HTML forms or exposes it via a meta tag for Single Page Applications (SPAs).

When the client submits a request, it includes the token in a custom request header (such as X-CSRF-Token). Because browsers enforce the Same-Origin Policy (SOP), malicious third-party websites cannot read the token from your domain or set custom headers on cross-origin requests. The server validates the token using constant-time string comparison to prevent timing attacks.

Furthermore, modern web applications can enforce Fetch Metadata Request Headers. When receiving a state-altering request, inspect the Sec-Fetch-Site header. If Sec-Fetch-Site: cross-site is detected on an internal administrative route, immediately reject the transaction with 403 Forbidden. Audit your headers and API security using the WeSecureX Security Headers Checker and Website Scanner.

typescript
// Secure CSRF Protection Middleware in Express.js / Node.js
import crypto from 'crypto';
import type { Request, Response, NextFunction } from 'express';

export function csrfProtection(req: Request, res: Response, next: NextFunction) {
  // Safe HTTP read methods do not alter state and bypass CSRF checks
  if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) {
    return next();
  }

  // Extract client token from custom header or form body
  const clientToken = req.headers['x-csrf-token'] || req.body?._csrf;
  const sessionToken = req.session?.csrfSecret;

  if (!clientToken || !sessionToken) {
    return res.status(403).json({ error: 'CSRF token missing or invalid.' });
  }

  // Constant-time string comparison prevents side-channel timing attacks
  const isMatch = crypto.timingSafeEqual(
    Buffer.from(String(clientToken), 'utf-8'),
    Buffer.from(String(sessionToken), 'utf-8')
  );

  if (!isMatch) {
    return res.status(403).json({ error: 'CSRF validation failed.' });
  }

  next();
}

Apply it with WeSecureX

Add a hostname you own or are allowed to test, run a scan, and open the findings for that target. A confirmed result includes the request WeSecureX sent and the response the site returned, so you can reproduce it, fix it in your own application, and rescan the same host to confirm the issue is gone. WeSecureX is automated testing, not a manual penetration test, and a clean report is not a promise that every weakness is gone.

Checks that belong with this topic

  • Set SameSite=Lax or SameSite=Strict on all authentication and session cookies.
  • Require HttpOnly and Secure flags on all session identifiers.
  • Implement cryptographically random anti-CSRF tokens verified with constant-time comparison.
  • Never allow GET requests to execute state-changing operations (such as password changes or transfers).
  • Check headers and cookie configurations using the WeSecureX Security Headers Checker.

Actionable Checklist

WeSecureX Platform · Surface Monitor

Application Attack Surface Analyzer

Inspect open ports, TLS certificate chains, HTTP headers, and API endpoint security posture.

Includes: TLS/SSL cipher suite & expiration monitoring · Security header verification (CSP, HSTS) · Subdomain asset discovery

Frequently Asked Questions

If your JWT is stored in JavaScript memory or LocalStorage and transmitted via the `Authorization: Bearer <token>` header, the application is immune to CSRF because browsers never attach `Authorization` headers cross-origin automatically. However, LocalStorage is vulnerable to XSS. If you store your JWT in an `HttpOnly` cookie to protect against XSS, you MUST implement CSRF defense.

CORS (Cross-Origin Resource Sharing) governs whether JavaScript on an untrusted origin can *read* the response of a cross-origin request. It does not stop the browser from *sending* the request or the server from executing the state change.

Use the [WeSecureX Security Headers Checker](/tools/security-headers-checker) to inspect cookie flags (`SameSite`, `HttpOnly`, `Secure`) and evaluate response security headers.

Authoritative Sources & References

  • OWASP Cross-Site Request Forgery Prevention Cheat SheetOWASP (technical)
    View Source
  • MDN Web Docs: SameSite cookiesMozilla (official)
    View Source

Continue exploring related technical architecture and defensive guides

Security Research & Engineering Articles

All articles