Back to Web App Security & OWASP Top 10
Web App Security & OWASP Top 10

What is Cross-Site Request Forgery (CSRF) and how do anti-CSRF tokens protect state-changing POST requests?

Anti‑CSRF tokens tie each state‑changing request to a server‑generated secret, preventing forged submissions.

R
Rahul Sharma 👑 Tier 3 Elite
Aug 9, 2026 · 2 min read
CSRF tricks a victim’s browser into sending an authenticated state‑changing request to a target site. Anti‑CSRF tokens bind the request to a user‑specific secret that the attacker cannot guess, causing the server to reject forged submissions. **How anti‑CSRF works** 1. **Token generation** – On each GET that renders a form, the server creates a cryptographically random value (e.g., 128‑bit) and stores it in the user’s session or a signed cookie (`XSRF‑TOKEN`). 2. **Token injection** – The value is embedded in the HTML, either as a hidden `` or as a JavaScript‑readable header meta tag. 3. **Client submission** – When the user submits the form (POST, PUT, DELETE), the token is sent back either in the request body or in the `X‑XSRF‑TOKEN` header (Ajax). 4. **Verification** – The server reads the token from the request and compares it to the stored value. A mismatch returns HTTP 403. 5. **Rotation** – After a successful verification, the token is regenerated to limit reuse. **Quick comparison** | Mechanism | Stored where | Sent via | Replay protection | |-----------|--------------|----------|-------------------| | Cookie‑only auth | HttpOnly cookie | Cookie header | No | | Anti‑CSRF token | Session or signed cookie | Body / `X‑XSRF‑TOKEN` header | Yes (per‑request) | **Express.js example (Node 18)** ```javascript const express = require('express'); const cookieParser = require('cookie-parser'); const csurf = require('csurf'); const app = express(); app.use(cookieParser()); app.use(express.urlencoded({ extended: false })); app.use(csurf({ cookie: { httpOnly: true, sameSite: 'strict' } })); app.get('/form', (req, res) => { res.send(` Send `); }); app.post('/submit', (req, res) => { res.send('OK'); }); ``` **Gotcha:** If you serve the same page from a CDN that strips or rewrites the hidden input, the token never reaches the server and every POST fails with 403. Ensure the CDN respects the token field or disable edge‑side injection for those endpoints.

Read the evidence

Sources used in this thread

Open the original material, compare the claims, and form your own view.

Community notes

Add context, not noise (0)

Corrections, lived experience, useful examples, and better sources belong here.

Nothing added yet. Be the first to make this thread more useful.
Click here to write a reply...
🔒

Authentication Required

Join Trendzza to begin your journey. Submit tasks, complete batches, help peers, and earn your way to Tier 3.