Security

Prevent CSRF Attacks: Fortify Your Web Apps Against Malicious Requests

Cross-Site Request Forgery (CSRF) remains a pervasive threat, tricking authenticated users into executing unwanted actions. Discover engineering-led strategies to prevent CSRF attacks and secure your web applications.

Krapton Engineering
Reviewed by a senior engineer12 min read
Share
Prevent CSRF Attacks: Fortify Your Web Apps Against Malicious Requests

In the evolving landscape of web application security, some threats, like Cross-Site Request Forgery (CSRF), stubbornly persist. Despite decades of awareness and well-documented prevention strategies, misconfigurations and overlooked edge cases continue to make CSRF a leading cause of security vulnerabilities, potentially leading to unauthorized transactions, data modifications, or complete account compromise.

TL;DR: Cross-Site Request Forgery (CSRF) tricks authenticated users into performing unintended actions on a web application. Effective prevention hinges on implementing anti-CSRF tokens for all state-changing operations, correctly configuring SameSite cookie attributes, and validating the origin of incoming requests. This multi-layered approach is crucial for hardening web applications.

Key takeaways

An empty computer lab with multiple workstations and large windows during the daytime.
Photo by Polina Zimmerman on Pexels
  • CSRF exploits trust between a user's browser and a web application, forcing authenticated users to execute actions without their consent.
  • Anti-CSRF tokens (Synchronizer Token Pattern) are the most robust defense, ensuring that only legitimate requests from your application are processed.
  • SameSite cookie attributes provide a foundational layer of defense by controlling when cookies are sent with cross-site requests.
  • Avoid using GET requests for any operation that changes application state or sensitive data.
  • Regularly audit your application's critical endpoints and session management for potential CSRF vulnerabilities.

Understanding Cross-Site Request Forgery (CSRF)

A cybersecurity professional monitors data systems in a dark room, emphasizing protection and vigilance.
Photo by Tima Miroshnichenko on Pexels

Cross-Site Request Forgery (CSRF), sometimes pronounced "sea-surf" or referred to as XSRF, is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated. The attacker constructs a malicious request that, when triggered by the victim's browser, appears to the vulnerable application as a legitimate request from the authenticated user. Because the victim's browser automatically includes session cookies and other authentication credentials with the request, the application cannot distinguish between a legitimate user-initiated action and a forged one.

Imagine a scenario where a user is logged into their banking website. In another browser tab, they visit a malicious website. This malicious site could embed an invisible form or an image tag pointing to a URL on the banking site that, if accessed with the user's session, transfers money. When the user's browser loads the malicious page, it automatically sends the authenticated banking session cookies along with the forged request, allowing the unauthorized transaction to occur.

Even in 2026, CSRF remains a relevant threat primarily due to:

  • Legacy Applications: Older systems often lack modern CSRF protections and are costly to refactor.
  • Complex SPAs: Single Page Applications (SPAs) with intricate state management and API interactions can introduce new CSRF vectors if not carefully designed.
  • Misconfiguration: Incorrect implementation of security headers, SameSite cookies, or anti-CSRF tokens can render protections ineffective.
  • Developer Oversight: New features or endpoints might be added without proper security review, reintroducing vulnerabilities.

Common CSRF Attack Vectors and Exploitation

CSRF attacks often leverage the browser's automatic handling of cookies and other authentication mechanisms. The core vulnerability typically lies in web applications that trust requests solely based on session cookies, without additional validation.

One common vulnerable pattern is when an application performs state-changing actions via a simple GET request. While rare in modern applications, some older systems or poorly designed APIs might still exhibit this. For example, a logout functionality implemented as GET /logout is not inherently a CSRF risk (as it's usually not a damaging action), but GET /transfer?to=attacker&amount=1000 certainly is.

Consider a simple web form that allows a user to change their email:

<!-- Vulnerable email change form -->
<form action="/settings/change-email" method="POST">
    <label for="email">New Email:</label>
    <input type="email" id="email" name="new_email" value="{{ user.email }}">
    <button type="submit">Update Email</button>
</form>

If this form is submitted without any CSRF protection, an attacker could craft a malicious page:

<!-- Malicious page hosted by attacker -->
<html>
  <body onload="document.forms[0].submit()">
    <form action="https://vulnerable-site.com/settings/change-email" method="POST">
      <input type="hidden" name="new_email" value="attacker@example.com" />
    </form>
  </body>
</html>

When an authenticated user visits the attacker's page, their browser automatically submits the hidden form along with their session cookie, changing their email on the vulnerable site to attacker@example.com without their knowledge. This could lead to account takeover.

In a recent client engagement, we identified a legacy payment gateway integration that relied purely on session cookies and a custom X-Auth header for critical actions. While not a direct CSRF token, the custom header was meant to prevent attacks. However, due to a misconfiguration in their CORS policy, the attacker could craft a request that bypassed the X-Auth header validation for certain cross-origin requests, effectively making the endpoint vulnerable to CSRF. We fixed this by enforcing strict CORS policies and introducing a proper anti-CSRF token validated server-side for all state-changing API calls.

Implementing Robust CSRF Protection

Preventing CSRF requires a multi-layered approach, combining server-side token validation with modern browser security features.

Anti-CSRF Tokens (Synchronizer Token Pattern)

The most widely accepted and robust defense against CSRF is the use of anti-CSRF tokens, often implemented via the Synchronizer Token Pattern. This involves:

  1. The server generates a unique, cryptographically random token for each user session.
  2. This token is embedded as a hidden field in all HTML forms and included in HTTP headers for AJAX/API requests.
  3. Upon receiving a request, the server verifies that the token submitted with the request matches the token associated with the user's session. If they don't match, the request is rejected.

This ensures that only requests originating from your application (which knows the valid token) can successfully execute state-changing operations. Frameworks like Express, Next.js, and Django provide middleware or built-in functions to simplify this process.

SameSite Cookies

The SameSite attribute for cookies provides a foundational layer of defense by instructing browsers on how to handle cookies with cross-site requests. As of 2026, most modern browsers default to Lax for cookies without an explicit SameSite attribute, providing a significant boost against CSRF. However, explicit configuration is always best practice.

  • SameSite=Lax: Cookies are sent with top-level navigations (e.g., clicking a link) but not with other cross-site requests (e.g., POST forms, image loads). This offers a good balance of security and usability.
  • SameSite=Strict: Cookies are only sent with requests originating from the same site as the cookie. This is the most secure but can be disruptive for legitimate cross-site use cases (e.g., third-party integrations).
  • SameSite=None; Secure: Cookies are sent with all cross-site requests, but only if they are served over HTTPS. This effectively opts out of SameSite protection and should only be used when absolutely necessary for specific cross-site functionalities, always with the Secure flag.

By correctly setting SameSite=Lax or Strict on your session cookies, you can prevent them from being sent with many types of forged requests.

Here's a hardened example of the email change form, incorporating an anti-CSRF token:

<!-- Hardened email change form with CSRF token -->
<form action="/settings/change-email" method="POST">
    <label for="email">New Email:</label>
    <input type="email" id="email" name="new_email" value="{{ user.email }}">
    <input type="hidden" name="_csrf_token" value="{{ csrf_token }}">
    <button type="submit">Update Email</button>
</form>

On the server side (e.g., Node.js with Express), you'd have middleware to handle this:

// Example using csurf middleware in Express
const csrf = require('csurf');
const express = require('express');
const app = express();

// Configure CSRF protection
const csrfProtection = csrf({ cookie: true });

app.use(cookieParser()); // Make sure cookie-parser is used before csurf
app.use(csrfProtection);

// Route to render the form with the token
app.get('/settings', (req, res) => {
  res.render('settings', { csrfToken: req.csrfToken() });
});

// Route to handle form submission
app.post('/settings/change-email', (req, res) => {
  // If we reach here, CSRF token has been validated by middleware
  const newEmail = req.body.new_email;
  // Update email logic...
  res.send('Email updated successfully!');
});

// Error handling for CSRF issues
app.use((err, req, res, next) => {
  if (err.code === 'EBADCSRFTOKEN') {
    res.status(403).send('Invalid CSRF token');
  } else {
    next(err);
  }
});

When NOT to use this approach

While anti-CSRF tokens are highly effective, they do introduce a slight overhead. For purely static content or APIs that are intentionally designed to be called cross-origin (e.g., public, unauthenticated APIs), CSRF tokens are unnecessary. Implementing them on such endpoints adds complexity without security benefit. Furthermore, for very high-throughput, unauthenticated API endpoints, the token generation and validation overhead, though typically in single-digit milliseconds, could be a minor performance consideration, though usually negligible compared to network latency or database operations. This is where a clear distinction between state-changing and idempotent/safe operations (like GET requests for data retrieval) is crucial.

Enjoying this article?

Like this article? Help us grow.

Choose Krapton as a preferred source on Google to see more of our engineering insights in Search. You only need to click once.

Best Practices for CSRF Prevention: A Developer's Checklist

Implementing robust CSRF protection requires diligence across your development lifecycle. Here’s a checklist to guide your team:

  • Use Anti-CSRF Tokens: Implement unique, cryptographically random anti-CSRF tokens for all state-changing operations (POST, PUT, DELETE, PATCH). Ensure tokens are generated per-session, stored securely server-side (or in a secure cookie for Double Submit Token pattern), and validated on every relevant request.
  • Configure SameSite Cookies: Explicitly set the SameSite attribute for all session-related cookies to Lax or Strict. Avoid SameSite=None unless absolutely required for specific cross-site functionalities, and always pair it with the Secure flag.
  • Avoid GET Requests for State Changes: Never use GET requests to perform actions that modify data or application state. GET requests should always be idempotent and safe.
  • Verify Origin/Referer Headers (as a secondary defense): For critical endpoints, consider validating the Origin or Referer HTTP headers to ensure requests originate from your domain. Be aware that these headers can be stripped or spoofed in certain scenarios, so they should not be the primary defense.
  • Secure Session Management: Ensure session cookies are marked HttpOnly (to prevent XSS from accessing them) and Secure (to ensure they are only sent over HTTPS). This prevents attackers from stealing session cookies, which could bypass CSRF protections.
  • Employ a Web Application Firewall (WAF): While not a primary CSRF defense, a WAF can provide an additional layer of protection by detecting and blocking suspicious requests, including those that might indicate a CSRF attempt.
  • Regular Security Audits and Penetration Testing: Periodically engage external security experts for penetration testing to identify overlooked CSRF vulnerabilities.

On a production rollout for a React-based SaaS product, we initially struggled with token management across SSR and client-side fetches. Our Next.js 15.2 App Router setup meant tokens needed to be securely passed from server components to client components without being exposed globally. We tried a custom context provider for the CSRF token, but this led to hydration mismatches. The solution involved using a dedicated server action to generate and return the token, which was then securely embedded in a hidden input for form submissions or fetched via an API endpoint for client-side API calls. This ensured the token was always fresh and correctly associated with the user's session, preventing CSRF attacks while maintaining a seamless user experience.

Verifying Your CSRF Protections

Once you’ve implemented CSRF protections, it's crucial to verify their effectiveness. This involves both manual testing and automated security scans.

Manual Verification Steps

  1. Identify Target Actions: Find all state-changing actions (e.g., changing password, making a payment, updating profile) in your application.
  2. Capture Request: Log in as a legitimate user, perform the target action, and capture the HTTP request using a browser's developer tools or a proxy like Burp Suite.
  3. Remove CSRF Token: Remove the anti-CSRF token (if present) from the captured request.
  4. Modify and Replay (Cross-Origin): Attempt to replay this modified request from a different origin (e.g., a simple HTML page on a different domain or a local file loaded in the browser). If the action is still successful, your CSRF protection is flawed.
  5. Test SameSite Configuration: Use developer tools to inspect your cookies. Ensure session cookies have the correct SameSite attribute (Lax or Strict). Test scenarios where cookies should or should not be sent with cross-site requests.

Automated Verification

  • Integration Tests: Write automated tests that simulate CSRF attacks by sending requests to your protected endpoints without a valid token. These tests should assert that the requests are rejected.
  • Security Scanners: Utilize DAST (Dynamic Application Security Testing) tools like OWASP ZAP or commercial scanners to automatically crawl your application and identify potential CSRF vulnerabilities.

Here's a comparison of the primary CSRF protection mechanisms:

MechanismPrimary DefenseComplexityBrowser SupportKey Benefit
Anti-CSRF TokensServer-side validation of unique tokensModerate (requires server-side generation/validation)Universal (framework-dependent)Highly robust, explicitly ties request to session.
SameSite CookiesBrowser-level cookie transmission controlLow (simple cookie attribute)Excellent (modern browsers default to Lax)Good baseline defense, easy to implement.
Origin/Referer Header CheckServer-side validation of request sourceLow (simple header check)Varies (headers can be missing/spoofed)Secondary defense, useful for edge cases.

For comprehensive protection against Cross-Site Request Forgery and other common web application security vulnerabilities, we recommend a multi-layered strategy that combines anti-CSRF tokens with appropriate SameSite cookie policies and rigorous testing. Krapton's software security services focus on implementing these robust defenses from the ground up.

FAQ

What is the difference between CSRF and XSS?

CSRF (Cross-Site Request Forgery) tricks an authenticated user into performing an unwanted action on a trusted site. XSS (Cross-Site Scripting) injects malicious client-side scripts into web pages viewed by other users. CSRF exploits the trust a site has in a user's browser, while XSS exploits the trust a user has in a site.

Are SameSite cookies enough to prevent CSRF?

While SameSite cookies (especially Lax or Strict) significantly mitigate many CSRF attack vectors, they are not a complete solution. They protect against certain types of cross-site requests but can be bypassed in specific scenarios. Anti-CSRF tokens offer a more robust and comprehensive defense, especially for state-changing POST requests.

Does a REST API need CSRF protection?

REST APIs that use cookie-based authentication and process state-changing requests are vulnerable to CSRF, similar to traditional web applications. If your API relies on cookies for session management, you absolutely need CSRF protection (e.g., anti-CSRF tokens in custom headers). Token-based authentication (like JWT in Authorization headers) is generally not susceptible to CSRF.

How do frameworks like Next.js or Express handle CSRF?

Frameworks like Next.js and Express don't provide CSRF protection out-of-the-box in their core, but they integrate well with established middleware. For Express, libraries like csurf are commonly used. In Next.js, especially with the App Router, developers typically implement CSRF tokens via server components, API routes, or server actions, ensuring tokens are passed securely to client components or forms for validation.

Building Secure Applications with Krapton

At Krapton, we understand that security is not an afterthought but a foundational pillar of successful software. Our principal-level software engineers and security strategists embed robust security practices into every stage of the development lifecycle, from initial architecture design to deployment and ongoing maintenance. We specialize in identifying and mitigating complex vulnerabilities like CSRF, ensuring your web applications are resilient against modern threats. Whether it's implementing secure authentication flows, hardening APIs, or ensuring compliance, our teams build with security at the forefront. Our Next.js developers, for instance, are adept at integrating secure token management and SameSite cookie policies into high-performance web applications.

Don't let security vulnerabilities compromise your business or user trust. Get a security-minded engineering team — book a free consultation with Krapton to discuss your software security needs and build a resilient digital future.

About the author

Krapton Engineering brings deep, hands-on experience in building and securing complex web and mobile applications for startups and enterprises globally. Our team of senior engineers regularly ships production-grade systems, tackling application security challenges like CSRF, API vulnerabilities, and secure authentication across various stacks, ensuring robust protection and compliance for high-stakes environments.

application securityweb securityowaspcsrfsecure codingsame-site cookiesanti-csrf tokenweb vulnerabilities
About the author

Krapton Engineering

Krapton Engineering brings deep, hands-on experience in building and securing complex web and mobile applications for startups and enterprises globally. Our team of senior engineers regularly ships production-grade systems, tackling application security challenges like CSRF, API vulnerabilities, and secure authentication across various stacks, ensuring robust protection and compliance for high-stakes environments.