Back to guides

GUIDE / security

How to Test for CSRF

Learn how to test for CSRF as a QA: token checks, cookie flags, SameSite, multi-step flows, safe staging methods, and a practical CSRF testing checklist.

By The Testing AcademyPublished July 9, 2026Updated July 9, 202619 min read

Session cookies say who is logged in; they do not prove the user meant to change their email, role, or payment method from your UI. How to test for CSRF gives QA a practical way to catch forged state-changing requests that ride a trusted browser session.

This guide shows how to test for CSRF as a QA: mapping state-changing requests, validating CSRF tokens, checking cookie flags and SameSite behavior, using safe staging methods, and writing defects developers can fix. You will also get test cases, comparison tables, common mistakes, and a checklist you can reuse each release.

For the broader QA security mindset, read security testing for QA. For the OWASP risk map, see OWASP Top 10 for testers. For proxy skills that help intercept requests, use the Burp Suite tutorial.

Ethics and Safety First

Before any CSRF testing:

  1. Work only in environments you are authorized to test.
  2. Prefer staging with synthetic accounts and data.
  3. Use your own test users, never other people's sessions.
  4. Avoid destructive actions when a non-destructive proof is enough.
  5. Coordinate if tests may trigger WAFs, fraud systems, or lockouts.
  6. Stop and escalate when you confirm a serious issue.

Security testing without permission is not initiative. It is a process violation.

What CSRF Is in Plain Language

Imagine a user is logged into bank.example in one browser tab. In another tab, they visit a malicious page. That page silently causes the browser to send a request to bank.example that transfers money or changes the account email. Because the browser automatically includes the session cookie, the bank may treat the request as legitimate.

CSRF succeeds when all of these are true enough in practice:

  1. The user has an authenticated browser context with the target site.
  2. The attacker can cause the browser to send a request to that site.
  3. The server accepts the request without proving it came from a real in-app user action.
  4. The request changes something valuable.

Modern defenses include anti-CSRF tokens, SameSite cookies, careful use of custom headers, re-authentication for sensitive actions, and avoiding state changes on unsafe methods. Your job is to verify those defenses actually work on real endpoints.

IssueCore problemTypical QA signal
CSRFForged authenticated request from browser trustState change without valid anti-CSRF proof
XSSAttacker script runs in site originScript executes or DOM sinks accept untrusted HTML
Session fixation/hijackAttacker uses or sets victim sessionSession token handling flaws
Broken access controlUser can act beyond authorizationHorizontal or vertical privilege success

CSRF is about forging intent. Access control is about forging or abusing permission. Test both. A request can be CSRF-protected and still vulnerable to IDOR if object IDs are guessable. Pair this topic with authentication and authorization testing.

Where CSRF Risk Lives in Real Products

High value targets:

  • Change password or email.
  • Add payment method.
  • Transfer funds or change payout settings.
  • Grant admin role or invite users.
  • Delete projects, records, or accounts.
  • Change 2FA settings.
  • OAuth connect or disconnect flows.
  • Admin configuration POSTs.

Medium risk patterns:

  • Save profile preferences that affect security or privacy.
  • Bulk actions on selected records.
  • "Log out all sessions" style controls.
  • Multi-step wizards with final commit requests.

Lower priority, but still check side effects:

  • Endpoints that look like GET reads but mutate state.
  • JSON APIs called from browsers with cookie auth.
  • Mobile webviews that share cookie jars.

Defenses You Should Understand Before Testing

Anti-CSRF tokens

The app embeds a secret token in forms or responses. State-changing requests must include that token. The server validates it against the session.

Test questions:

  • Is a token required?
  • Is a missing token rejected?
  • Is an empty token rejected?
  • Is an old token after login or logout rejected?
  • Can a token from user A be used with user B's session?
  • Is the token validated server-side, or only checked by frontend JavaScript?

SameSite=Lax, Strict, or None changes when cookies are sent on cross-site requests.

Test questions:

  • What is the actual Set-Cookie value in staging and production-like configs?
  • Are sensitive cookies Secure and HttpOnly where appropriate?
  • Do browsers in your matrix behave as assumed?
  • Are there endpoints still vulnerable under realistic cross-site conditions?

Custom request headers

Some SPAs rely on headers like X-Requested-With that are hard for simple cross-site form posts to set under browser CORS rules. This can help, but only if CORS and cookie policies are correct.

Re-authentication and step-up auth

Sensitive actions may require password re-entry, OTP, or WebAuthn. That reduces CSRF impact even if a request is forged.

Idempotency and method discipline

State changes should use safe server-side verification and appropriate methods. A destructive GET is a red flag.

Step by Step: How to Test for CSRF

Step 1: Map state-changing browser requests

Log in as a test user. Use browser devtools or an intercepting proxy.

Capture:

  • URL
  • Method
  • Content type
  • Cookie dependency
  • Body parameters
  • Custom headers
  • Whether a CSRF token is present
  • Whether the action is sensitive

Build a table:

ActionMethodEndpointAuth via cookies?CSRF token present?Sensitivity
Update emailPOST/api/account/emailYesYesHigh
Delete projectDELETE/api/projects/{id}YesHeader tokenHigh
Save themePUT/api/prefs/themeYesNoLow

Focus first on high sensitivity rows.

If the API uses only a bearer token from localStorage and never cookies, classic cookie CSRF may not apply the same way. Many apps are hybrid. Verify reality rather than architecture slides.

Checks:

  • Remove Authorization header and replay with cookies only.
  • Remove cookies and replay with Authorization only.
  • Observe which credential path the server accepts.

CSRF risk is highest when browsers auto-attach credentials.

Step 3: Replay without the CSRF token

Using a proxy repeater:

  1. Capture a valid state-changing request.
  2. Drop the CSRF token field or header.
  3. Send the request with the still-valid session cookie.
  4. Observe accept vs reject.

Expected secure result: 403, 401, or an application error that refuses the change. The server state must not change.

Also try:

  • Empty token value.
  • Token value null.
  • Truncated token.
  • Token with extra characters.
  • Token parameter moved from header to body or reverse.

Step 4: Replay with another user's token

  1. Log in as User A, capture CSRF token A.
  2. Log in as User B in another session, capture a valid state-changing request for B.
  3. Replace B's token with A's token while keeping B's session cookies.
  4. Send and observe.

Secure systems bind tokens to sessions or otherwise reject mismatches.

Step 5: Test token lifecycle

Tokens should not live beyond useful trust.

Cases:

  • Reuse token after successful password change flow, if one-time use is expected.
  • Reuse token after logout and login.
  • Use token issued before session regeneration.
  • Multi-tab usage with concurrent tokens if the app allows it.

Document the intended design. Some frameworks allow multiple valid tokens per session. The key is that tokens from outside the valid set never work.

Step 6: Attempt a simplified forged request

In staging, create a local HTML file or lab page that auto-submits a form to the target endpoint.

Example teaching shape (use only on authorized staging):

<html>
  <body onload="document.forms[0].submit()">
    <form method="POST" action="https://staging.example.com/account/email">
      <input type="hidden" name="email" value="attacker-controlled@example.com" />
    </form>
  </body>
</html>

Then:

  1. Log into the staging app in the same browser.
  2. Open the lab page.
  3. Check whether email changed.

If the app requires a CSRF token you do not know, the forge should fail. If it succeeds without any token, you likely found a real issue.

For JSON APIs, simple HTML forms may not send application/json. Still test:

  • Form posts to endpoints that also accept form encoding.
  • CORS preflight behavior for credentialed cross-origin XHR or fetch.
  • Any endpoint that accepts multiple content types.

In response headers, review session cookies:

Set-Cookie: session=...; HttpOnly; Secure; SameSite=Lax; Path=/;

Evaluate:

  • Missing Secure on HTTPS-only apps.
  • Missing HttpOnly on session cookies that do not need JS access.
  • SameSite=None without strong compensating controls.
  • Over-broad Path or Domain attributes.

Cookie flags are defense in depth. Application CSRF tokens still matter.

Step 8: Test method and side-effect surprises

Find any GET or cacheable request that mutates state:

GET /project/123/delete
GET /account/api-keys/rotate

These are historically dangerous for CSRF and accidental prefetch. Report them even if other CSRF controls exist.

Step 9: Cover multi-step and sensitive flows

Flows that need extra attention:

  • Email change confirmation links.
  • Bank account updates requiring two steps.
  • Admin bulk update after search filters.
  • "Confirm destroy" pages that finalize via POST.

Verify every state-changing hop is protected, not only the first form load.

Step 10: Retest after login state changes

Perform:

  1. Login.
  2. Complete a protected action successfully.
  3. Logout.
  4. Attempt replay of the old request with old cookies and tokens.
  5. Login again and ensure old tokens do not incorrectly authorize new sessions.

Session fixation and CSRF often meet at login boundaries.

Example CSRF Test Cases for QA

IDTitlePreconditionsStepsExpected resultPriority
TC-CSRF-01Reject missing token on email changeLogged-in user, known email change requestReplay request without CSRF tokenRequest rejected; email unchangedHigh
TC-CSRF-02Reject empty tokenSame as aboveSend empty token valueRejected; no state changeHigh
TC-CSRF-03Reject foreign tokenUsers A and B existUse A's token with B sessionRejected; no state changeHigh
TC-CSRF-04Form forge without token failsUser logged in, staging lab page readyOpen auto-submit forge page for password or email changeNo sensitive change occursHigh
TC-CSRF-05Session cookie flags presentFresh loginInspect Set-CookieSecure/HttpOnly/SameSite appropriate for designHigh
TC-CSRF-06No state-changing GETCrawl app featuresAttempt delete or rotate via GET if links existNo mutation via GETHigh
TC-CSRF-07Step-up auth for bank changeUser with payment settingsStart payout account changePassword or OTP required before commitMedium
TC-CSRF-08Token invalid after logoutCaptured old requestLogout, replay old cookies/tokenRejectedMedium

Using Burp or Browser Tools Effectively

Practical workflow:

  1. Turn on intercept or logger.
  2. Perform the sensitive action once normally.
  3. Send the request to repeater.
  4. Create variants: no token, bad token, swapped token, method change.
  5. After each send, verify UI and database or API read-back for real state change.
  6. Save evidence: request, response, before/after values.

Do not trust response text alone. Confirm whether the resource actually changed.

If you are new to intercepting proxies, follow the Burp Suite tutorial and keep scope locked to staging.

SPA, API, and Mobile Web Notes

If the SPA stores session in cookies and calls APIs from JavaScript, CSRF defenses must protect those APIs. Frontend-only checks are not enough.

Bearer token in localStorage

Classic CSRF against cookie session may not apply, but XSS becomes more catastrophic because script can read the token. Security work shifts; it does not disappear.

Mobile webviews

Shared cookie jars and embedded browsers can surprise you. Test the actual client that matters.

Third-party payment or support widgets

If widgets trigger account changes via your domain, include those callbacks in CSRF mapping.

How to Write a Strong CSRF Bug Report

Weak:

CSRF possible on profile.

Strong:

Title: Email change API accepts POST without CSRF token
Environment: staging.example.com, test user qa+csrf@example.com
Endpoint: POST /api/account/email
Auth: session cookie `session`
Steps:
1. Log in as test user.
2. Capture valid email change request.
3. Remove `X-CSRF-Token` header and `csrf` body field.
4. Resend with valid session cookie.
Actual: 200 OK, email changed to attacker-controlled value.
Expected: 403 and no email change without valid CSRF token bound to session.
Impact: Attacker-hosted page could change victim email if victim is logged in, enabling account takeover via password reset.
Evidence: before/after account export, repeater screenshots, sanitized request dump
Recommended fix direction: enforce server-side anti-CSRF validation; verify SameSite cookie settings; consider step-up auth for email change.

Always include impact path. Engineers prioritize faster when account takeover is explicit.

Common Mistakes When Testing CSRF

Mistake 1: Testing only one form

Teams validate the profile save form and ignore admin delete endpoints, JSON APIs, and multi-step commits.

Mistake 2: Checking for token presence only

A token in the HTML does not prove server validation. Always remove or alter it and confirm rejection.

Mistake 3: Forgetting to verify state change

A 200 response with no change, or a 500 with a partial change, needs careful interpretation. Read the resource after the attempt.

Mistake 4: Assuming SameSite ends the discussion

SameSite helps a lot, but apps still misconfigure cookies, support old clients, or expose endpoints that remain forgeable. Test the real combination.

Mistake 5: Confusing CORS with CSRF

CORS protects cross-origin reads from JavaScript in browsers. CSRF is often about write side effects with cookies. They interact, but they are not the same control.

Mistake 6: Running destructive forges on production

Changing real emails or deleting real projects to "prove" CSRF is reckless. Use staging and reversible actions.

Mistake 7: Ignoring low privilege users

CSRF on a basic user can still enable account takeover. Admin CSRF can be catastrophic. Test both.

Mistake 8: No regression after framework upgrades

Auth library upgrades can change token filters. Keep a small CSRF regression pack.

CSRF Testing Checklist

[ ] Authorization and staging confirmed
[ ] State-changing endpoints mapped
[ ] Cookie vs bearer auth identified
[ ] Missing token rejected
[ ] Empty/invalid token rejected
[ ] Cross-user token rejected
[ ] Logout invalidates old request auth
[ ] No state-changing GET found
[ ] Cookie Secure/HttpOnly/SameSite reviewed
[ ] Sensitive actions have step-up auth where required
[ ] Multi-step final commit protected
[ ] SPA JSON endpoints included
[ ] Before/after state verified for each attempt
[ ] Defects include impact path and evidence
[ ] Regression cases added after fixes

How CSRF Fits a Broader Security Test Strategy

CSRF testing sits beside:

  • Authentication session tests.
  • Access control and IDOR tests.
  • XSS tests, because XSS can bypass many CSRF defenses by acting inside the origin.
  • API security checks for cookie-authenticated routes.

Use OWASP Top 10 for testers to prioritize. Use security testing for QA to keep scope ethical and repeatable. For account permission bugs that often appear near the same endpoints, study authentication and authorization testing.

Practice Path for Teams

A practical team drill:

  1. Pick one staging app feature that changes email or roles.
  2. Map the request in a proxy.
  3. Run the eight core CSRF cases from the table above.
  4. File one sample report with full evidence quality, even if no bug is found (as a dry run).
  5. Add two automated or scripted regression checks if your stack allows.

To build broader security testing instincts in battle-style practice, create an account at QABattle sign-up and use security-oriented challenges where available in battles.

Many modern front ends call JSON APIs like this:

POST /api/settings/email HTTP/1.1
Host: app.example.com
Content-Type: application/json
Cookie: session=...
X-CSRF-Token: 3f2c...
{"email":"new@example.com"}

Your tests should confirm:

  1. The API rejects requests without the CSRF header or body token.
  2. CORS does not allow arbitrary third-party origins to send credentialed requests successfully.
  3. The token is not fixed across all users.
  4. The token is not derivable from pure client-side guesswork.

From a foreign origin in a browser lab page, attempt credentialed fetch to the staging API. Expected secure behavior is that the browser blocks reading the response or the preflight fails, and the server still requires CSRF proof for unsafe methods even if something slips through misconfiguration.

Remember: CORS is not a complete CSRF substitute, but misconfigured CORS plus cookie auth can widen impact.

Some apps store a CSRF value in a cookie and require the same value in a header or form field.

Test ideas:

  • Modify header token while leaving cookie token unchanged.
  • Modify cookie token while leaving header unchanged.
  • Remove one of the two.
  • Use User A cookie token with User B session cookie if multiple cookies exist.

Secure validation requires server-side comparison that is not bypassable by simply setting both values to attacker-chosen strings when the session binding is weak. If you can set a CSRF cookie from a cross-site context and then match it, the pattern may be flawed. Escalate such findings to security engineering for deeper review.

Synchronizer Token Pattern Checks

Classic server-rendered apps embed tokens in HTML forms.

Test ideas:

  • Scrape token from page source as the legitimate user, then try to use it from another browser session.
  • Confirm token rotates according to design after login.
  • Confirm token is sufficiently long and not predictable like csrf=1001.
  • Confirm HTTPS pages do not leak tokens over mixed content.

Predictable tokens are almost as bad as missing tokens.

CSRF and XSS Interaction

If an attacker has XSS on your origin, many CSRF defenses weaken because script can read tokens and perform actions as the user. That does not make CSRF testing useless. It means:

  • XSS findings are often higher severity.
  • CSRF defenses still protect users from simple cross-site forgeries without XSS.
  • Defense in depth remains valuable.

When you find XSS and weak CSRF on the same flow, report both and explain combined impact carefully.

Multi-Tab and Back Button Scenarios

Real users keep multiple tabs open.

Cases:

  1. Open settings in two tabs.
  2. Submit email change in tab 1.
  3. Submit another change in tab 2 with the older token if the UI still shows it.
  4. Observe whether the app handles stale tokens gracefully without opening a bypass.

A secure app may accept multiple valid tokens per session or may reject stale ones. Either can be fine. A bug is when stale or foreign tokens authorize unintended changes, or when error handling confuses users into unsafe retries without protection.

CSRF Test Data and Environment Tips

Make staging easy to test:

  • Provide a dedicated CSRF lab user.
  • Allow short-lived sessions without flaky captchas for test accounts.
  • Log CSRF failures with request IDs you can cite in defects.
  • Document intended token header names for QA.
  • Avoid production-only middleware differences that make staging results meaningless.

If staging has no CSRF middleware but production does, your tests are fiction. Align security middleware across environments as much as possible.

Sample Exploratory Charter

Charter: Explore CSRF defenses on account takeover related actions
Time box: 90 minutes
Setup: two test users, proxy, staging
Targets: email change, password change, session logout-all, MFA disable
Actions: remove tokens, swap tokens, forge forms, inspect cookies, check GETs
Output: notes, at least one solid repro or residual risk statement

Exploratory charters catch flows checklist authors forget, such as "disconnect Google OAuth" or "delete API token."

Mapping CSRF Cases into Automation

Not every CSRF case belongs in CI, but some do:

  • API rejects missing CSRF header on a canary endpoint.
  • API rejects obviously invalid token on that endpoint.
  • Security smoke that session cookie attributes still include expected SameSite flags in staging.

Avoid brittle tests that scrape highly dynamic tokens through a full UI unless your framework already does auth well.

Collaboration Notes for Developers

When filing CSRF issues, offer reproduction that fits developer tools:

  1. Exact endpoint and method.
  2. Minimal request headers.
  3. Before and after resource state.
  4. Whether UI or only API is affected.
  5. Suggested regression test idea.

Developers fix faster when they can paste a failing request into their HTTP client.

Extended CSRF Checklist for High Risk Apps

Account takeover surfaces
[ ] Email change
[ ] Password change
[ ] Password reset confirmation side effects
[ ] MFA enable/disable
[ ] Recovery codes regenerate
[ ] OAuth connections

Money and admin surfaces
[ ] Payout bank change
[ ] Transfer or refund actions
[ ] Role grant and invite accept
[ ] API key create/delete
[ ] Organization delete

Platform surfaces
[ ] Webhook URL change
[ ] SSO configuration
[ ] Billing contact change

If your product has these surfaces, CSRF testing is not optional hygiene. It is core release risk control.

Closing Perspective

Knowing how to test for CSRF is ultimately about proving intent. Sessions say who is logged in. CSRF defenses help say whether that person actually meant to perform the action from your application UI. Test the difference on every state-changing path that can hurt a user or your business.

Conclusion

Knowing how to test for CSRF means more than searching for a token field in a form. It means mapping state-changing requests, proving the server rejects forged or tokenless calls, checking cookie behavior, verifying real state outcomes, and focusing on actions that enable takeover or fraud.

CSRF remains relevant in cookie-authenticated web apps, admin consoles, and hybrid SPAs. Build a small, ruthless regression pack around password, email, payment, and role changes. When those flows refuse forged requests every time, you have removed an entire class of "user did not mean to do that" disasters from your release risk.

FAQ

Questions testers ask

How do you test for CSRF as a QA engineer?

In an authorized environment, identify state-changing requests that rely on cookies or browser auth, then replay them without a valid CSRF token or from a cross-site context. Confirm the server rejects forged requests, check cookie SameSite and header validations, and retest after login, logout, and multi-step flows.

What is a CSRF attack in simple terms?

Cross-site request forgery tricks a victim's browser into sending an authenticated request to a site where the user is already logged in. If the server cannot tell a real user action from a forged one, it may change email, transfer funds, or alter settings without the user's intent.

Does SameSite=Lax fully prevent CSRF?

SameSite cookie attributes reduce many classic CSRF cases, especially with Lax or Strict settings, but they are not a complete substitute for application-level defenses on all flows. Test actual request methods, cookie settings, browser differences, and any endpoints that still accept cross-site authenticated calls.

Which requests should CSRF tests prioritize?

Prioritize state-changing actions: password change, email change, funds transfer, role changes, deleting data, payment method updates, and admin operations. Read-only GET fetches are usually lower priority unless they trigger side effects, which they should not.

Can I test CSRF safely on production?

Prefer staging with test accounts. Production CSRF tests can alter real user data or trigger alerts. Only test production under explicit authorization, non-destructive scope, and clear rules of engagement. Never target other users' accounts.

What is the difference between CSRF and XSS?

CSRF abuses the browser's automatic sending of credentials to make unwanted requests. XSS injects script into a page and can often do more, including reading responses and performing actions with full page privileges. Both are serious, but test techniques and fixes differ.