Vulnerability guide

Cross-Site Request Forgery vulnerability

Learn what Cross-Site Request Forgery is, how CSRF abuses authenticated browser sessions, where it appears in web applications and APIs, and how to prevent it with anti-CSRF tokens, SameSite cookies, origin checks, and safe request design.

Web application securitySession securityCWE-352Prevention guide

What Cross-Site Request Forgery is

Cross-Site Request Forgery, usually shortened to CSRF, is a web application vulnerability where a site accepts a state-changing request just because the browser includes the user's valid session cookies. The attacker does not need to know the user's password or read the response. The weakness is that the application cannot tell whether the request came from a real user action inside the trusted product or from another site that caused the browser to send it.

A simple way to think about CSRF is this: authentication proves who the browser is logged in as, but it does not prove that the logged-in user intentionally clicked the button, submitted the form, or approved the change. If a banking, billing, admin, or account settings endpoint relies only on cookies and accepts predictable requests, another website may be able to trigger the same action through the victim's browser.

CSRF is most dangerous on actions that change something: email address changes, password reset setup, payment details, team invitations, role updates, subscription changes, file deletion, admin settings, or anything that performs a transaction. Read-only pages are usually less exposed, but they still deserve careful design if they trigger side effects, prefetching, analytics writes, or sensitive workflow transitions.

How CSRF works

CSRF depends on normal browser behavior. When a user is signed in to an application, the browser often attaches that application's cookies to matching requests automatically. If a separate site can cause the browser to make a request to the application, the application may receive a request that looks authenticated even though the user never intended that action.

The vulnerability usually appears when three conditions meet: the user is authenticated, the target endpoint performs a state-changing action, and the application accepts the request without a secret request token, a reliable origin check, or another proof of user intent. The attacker normally cannot read the response because of browser same-origin rules, but the action may still complete.

Strong CSRF defenses add a server-verifiable signal that a different site cannot easily create. That signal may be a per-session or per-request anti-CSRF token, strict SameSite cookie behavior, Origin or Referer validation, custom headers for APIs, and re-authentication or step-up checks for sensitive workflows.

Unsafe state-changing request
app.post('/account/email', requireSession, async (req, res) => {
  await users.updateEmail(req.user.id, req.body.email)
  res.redirect('/settings')
})

This route updates account data after checking only that the request has a valid session. If the browser sends the session cookie automatically, the route has no second signal proving that the user intentionally submitted the change from the trusted interface.

Safer request with CSRF proof
app.post('/account/email', requireSession, verifyCsrfToken, verifyTrustedOrigin, async (req, res) => {
  await users.updateEmail(req.user.id, req.body.email)
  res.redirect('/settings')
})

This route still requires authentication, but it also verifies a server-issued CSRF token and checks the request origin before changing account data. Sensitive flows can add re-authentication, step-up MFA, or explicit confirmation when the business risk is high.

Visual flow

CSRF request path compared with a protected flow

The difference is not whether the browser is authenticated. The difference is whether the server can verify that the state-changing request was created by the trusted application flow.

Forged request path
  1. 1

    User is already signed in

    The browser holds a valid session cookie for the target application.

  2. 2

    Another site triggers a request

    A page outside the product causes the browser to submit a request to a state-changing endpoint.

  3. 3

    Cookies are attached automatically

    The browser sends the session cookie because the request targets the signed-in application.

  4. 4

    Server accepts cookie-only proof

    The endpoint changes data without checking a CSRF token, trusted origin, or explicit user confirmation.

Protected request path
  1. 1

    Trusted page receives a token

    The application includes a server-generated CSRF token in the legitimate form or request setup.

  2. 2

    Browser submits from the app

    The request carries the session cookie and a token or header that another site cannot create correctly.

  3. 3

    Server validates intent

    The server verifies the token, checks the origin where appropriate, and confirms authorization for the action.

  4. 4

    Action is logged and monitored

    Sensitive changes are recorded with user, session, source, and outcome signals for detection and response.

Why CSRF matters

CSRF can turn a victim's browser into an unwilling messenger for actions the victim did not choose. The attacker may not see the response, but many damaging operations do not require response visibility. A single accepted request can change an account, invite a user, start a workflow, approve a setting, or weaken a security control.

The business impact depends on the affected endpoint. CSRF on a low-risk preference setting may be annoying. CSRF on billing, identity, admin, or data-management functionality can create account abuse, data exposure, fraud, operational disruption, and audit findings.

Account manipulation

Attackers may cause changes to email addresses, profile data, notification settings, linked accounts, or recovery options if those flows lack request-intent checks.

Unauthorized business actions

A vulnerable workflow may accept unwanted approvals, invitations, role changes, subscription updates, order actions, or administrative configuration changes.

Security control weakening

CSRF can be especially harmful when it disables MFA, changes webhook targets, rotates API keys, adjusts access policies, or edits trusted integration settings.

Privacy and compliance risk

Unwanted state changes around personal data, billing records, account ownership, or regulated workflows can create disclosure duties, contractual issues, and loss of trust.

Operational disruption

Bulk or repeated forged actions can create support load, noisy audit trails, failed workflows, or unexpected configuration drift across customer workspaces.

Common CSRF forms and mistakes

CSRF is not tied to one programming language or one browser feature. It appears wherever an application accepts a cross-site request as if it were a user-approved action. Modern browser defaults reduce some exposure, but they do not remove the need to design state-changing endpoints carefully.

FormWhat to understand
Form-based CSRFA state-changing POST endpoint accepts form data with only a session cookie and no anti-CSRF token or trusted origin validation.
State-changing GET requestsA link, image load, prefetch, crawler, or embedded resource can trigger an action because the application uses GET for operations that modify state.
API CSRFA JSON or API endpoint relies on cookies, permits simple cross-site requests, uses permissive CORS, or fails to require a custom header and token.
Login CSRFA victim may be silently logged into an account chosen by an attacker, which can confuse actions, tracking, saved data, or later account flows.
Client-side CSRFTrusted JavaScript reads untrusted URL, fragment, message, or storage data and uses it to build authenticated requests inside the application.
SameSite overconfidenceTeams rely only on cookie defaults and forget legacy browsers, subdomain trust, cross-site redirects, embedded flows, or endpoints that still need explicit proof.
Token implementation mistakesCSRF tokens are reused incorrectly, not tied to a session, accepted from cookies without signing, leaked into URLs, or skipped on newer API routes.

Where CSRF appears

CSRF should be considered anywhere a browser-authenticated request can change server-side state. The most important question is not whether the endpoint has a form; it is whether another site could cause the browser to send a valid-looking request without the user's intent.

  • Account settings such as email, password, profile, notification, recovery, language, and security preferences.
  • Billing, subscription, plan changes, saved payment methods, invoices, credits, refunds, and checkout-adjacent workflows.
  • Team and tenant administration including invites, role changes, project settings, API keys, webhooks, integrations, and SSO configuration.
  • Content workflows such as publishing, deleting, archiving, approving, importing, exporting, sharing, and changing ownership.
  • Support dashboards, internal admin panels, moderation tools, customer impersonation features, and privileged operations.
  • Cookie-authenticated APIs, mobile-web hybrid flows, GraphQL mutations, background sync endpoints, and AJAX routes.
  • Legacy routes, feature flags, hidden forms, one-click links, email actions, callback URLs, and endpoints added outside the main framework protection layer.

Related vulnerability guides

How to prevent CSRF

CSRF prevention works best as a layered design. The durable fix is to require proof that a state-changing request was created by the trusted application, not just by a browser that happens to carry a valid session cookie. For most server-rendered web applications, framework-supported anti-CSRF tokens are the first control to enable and test.

SameSite cookies, Origin and Referer checks, Fetch Metadata headers, custom request headers for APIs, and careful CORS configuration all help reduce exposure. They should support the core request-intent check, not replace it blindly across every workflow.

Use anti-CSRF tokens

Require an unpredictable token for state-changing requests. Tie it to the session or sign it securely, validate it server-side, and avoid putting it in URLs or logs.

Prefer framework protections

Enable the CSRF middleware provided by the framework and add regression tests so new routes, mutations, and forms do not bypass it accidentally.

Set SameSite cookies carefully

Use SameSite=Lax or Strict where product flows allow it, combine it with Secure and HttpOnly, and understand where cross-site redirects or embedded flows still need explicit controls.

Validate Origin and Referer

For sensitive state changes, verify the request origin against trusted hosts. Treat missing or unexpected values carefully and document rollout behavior for proxies and privacy tools.

Avoid state changes with GET

Keep GET, HEAD, and similar safe methods read-only. Use POST, PUT, PATCH, or DELETE for mutations and still protect them with CSRF defenses.

Require non-simple API requests

For cookie-authenticated APIs, require custom headers and strict content types, avoid permissive CORS, and validate preflight behavior before relying on browser enforcement.

Add step-up checks for high-risk actions

Use re-authentication, MFA confirmation, explicit review screens, or transaction signing for sensitive actions such as MFA changes, API key rotation, payment updates, and admin role changes.

Monitor and log state changes

Record user, session, action, origin, outcome, and denial signals for sensitive routes. Make unusual patterns visible without logging secrets or raw token values.

Detection and response

CSRF detection combines code review, route inventory, authorized testing, and runtime telemetry. Automated scanners can find some missing-token patterns, but the most reliable review follows each state-changing endpoint and asks what proves user intent.

Signs of possible CSRF include state changes with unexpected Origin or Referer values, sensitive operations with no token validation, unusual account changes immediately after external navigation, support reports about actions users do not remember, and repeated denied token checks from the same source patterns.

  1. 1

    Inventory mutating endpoints

    List every route, controller, GraphQL mutation, form, AJAX handler, and background callback that changes state or starts a workflow.

  2. 2

    Check token coverage

    Verify each browser-authenticated mutation requires a valid anti-CSRF token or an equally strong framework-supported request-intent mechanism.

  3. 3

    Review cookies and CORS

    Confirm SameSite, Secure, HttpOnly, allowed origins, credentials mode, custom headers, and content types match the intended browser trust model.

  4. 4

    Test with authorization

    Use owned test accounts and approved environments to confirm that cross-site requests without the right token, origin, or headers are rejected.

  5. 5

    Watch runtime signals

    Monitor token validation failures, missing Origin or Referer values, unexpected source origins, sensitive account changes, high-volume form submissions, and user support reports.

  6. 6

    Patch and retest

    Enable framework protection, add missing token checks, fix unsafe methods, update tests, review logs for impact, and retest the original vulnerable path.

Developer checklist

Use this checklist during feature design, code review, and remediation. It intentionally focuses on decisions that can be verified in code, tests, and logs.

  • Every state-changing browser route requires an anti-CSRF token or equivalent framework protection.
  • CSRF tokens are unpredictable, validated server-side, tied to the session or signed, and never sent in URLs.
  • GET and other safe methods do not perform mutations, approval steps, deletion, or sensitive workflow transitions.
  • SameSite, Secure, and HttpOnly cookie settings are configured intentionally and tested against required product flows.
  • Sensitive actions validate Origin or Referer where appropriate and handle proxy and privacy-tool behavior consistently.
  • Cookie-authenticated APIs avoid permissive CORS and require headers or content types that cross-site forms cannot send silently.
  • High-risk changes use re-authentication, step-up MFA, explicit confirmation, or transaction review.
  • Client-side JavaScript does not build authenticated requests from untrusted URL fragments, postMessage data, storage, or external content.
  • New forms, GraphQL mutations, API handlers, admin actions, and legacy routes are covered by regression tests.
  • Logs capture token failures, suspicious origins, denied actions, and sensitive state changes without storing secrets.

Cross-Site Request Forgery FAQ

What is a Cross-Site Request Forgery vulnerability?

A CSRF vulnerability exists when an application accepts a state-changing request from a user's browser without verifying that the user intentionally initiated it from the trusted application.

Is CSRF the same as XSS?

No. XSS runs untrusted script inside a trusted page, while CSRF causes a browser to send an authenticated request to a trusted application. XSS can sometimes bypass CSRF defenses by reading tokens or making same-origin requests, so both issues matter.

Do SameSite cookies fully prevent CSRF?

SameSite cookies reduce many common CSRF paths, but they should usually be treated as defense-in-depth. Product flows, browser differences, cross-site redirects, subdomains, and APIs can still require tokens and origin validation.

Why are anti-CSRF tokens effective?

A valid anti-CSRF token gives the server a request-specific or session-bound secret that another site cannot reliably create. If the token is missing or invalid, the server can reject the state-changing request.

Can APIs have CSRF vulnerabilities?

Yes. Cookie-authenticated APIs can be vulnerable when they accept simple cross-site requests, use permissive CORS, or fail to require custom headers, strict content types, and server-side request-intent validation.

What actions need CSRF protection?

Protect any browser-authenticated action that changes state: profile updates, billing changes, team administration, content publishing, account security settings, API key management, webhooks, and admin workflows.

What is the best first step to prevent CSRF?

Enable and test the framework's CSRF protection for all state-changing browser routes, then layer SameSite cookies, Origin validation, safe HTTP methods, API header requirements, and step-up checks for sensitive actions.

References and further reading

The guidance above is rewritten in original wording from established application security references. Use these sources for deeper implementation details, testing methodology, and framework-specific recommendations.