Stop 05 · Vulnerabilities & OWASP Top 10Topics · 4/11

Cross-Site Request Forgery (CSRF)

Part of the Cybersecurity Roadmap

In short

Your browser attaches cookies automatically, even when a different website triggers the request. CSRF abuses that habit to make logged-in users perform actions they never chose.

Tricking a logged-in user's browser into submitting an unwanted request to a site they're authenticated to — exploiting the browser's automatic inclusion of session cookies.

The blob happily signs a tall stack of papers while a hand from the side slips in one more sheet.

Think of it like this

Signing the pile without reading

A busy hostel warden signs a tall pile of leave forms every evening. Someone slips an extra form into the pile, and it gets signed with the rest. The fix: only sign forms that carry the office's own stamp, which outsiders can't copy.

Watch it happen

A forged request gets turned away

Your browser
Other site
bank.example

login, cookie set

1/6You log in. The bank sets a session cookie with SameSite=Lax.

The big ideas

What you need to know

Cookies are the trigger

CSRF works because the browser adds credentials by itself. Auth headers your own JavaScript sets aren't added by other sites.

SameSite cookies

SameSite=Lax or Strict keeps the cookie off cross-site POSTs. Many browsers default to Lax, but set it explicitly.

Anti-CSRF tokens

A random token in each form, checked on the server. Other sites can't read your pages, so they can't copy it.

GET never changes data

Deleting or paying through a GET link is asking for trouble. Use POST, PUT or DELETE for changes.

See it in code

Walk through the code

ts
1app.use(session({2  secret: process.env.SESSION_SECRET,3  cookie: { httpOnly: true, secure: true, sameSite: "lax" },4}));5 6// Reject state-changing requests from other sites7app.use((req, res, next) => {8  if (req.method === "GET" || req.method === "HEAD") return next();9  const origin = req.get("Origin");10  if (origin !== "https://shop.example.in") {11    return res.status(403).json({ error: "Cross-site request blocked" });12  }13  next();14});

1/3The session cookie is HttpOnly, HTTPS only and SameSite=Lax, so other sites' POSTs arrive without it.

Layer this with a CSRF token in your forms, which most frameworks offer built in. Two checks beat one.

Save yourself the pain

Common mistakes

Oops

Setting SameSite=None on the session cookie to fix a login bug.

Do this instead

None removes the protection. Use it only when a cross-site setup truly needs it, and always with Secure plus a token.

Oops

Thinking a JSON API is safe from CSRF just because it uses JSON.

Do this instead

If auth is a cookie, plan for CSRF. Check Origin, require a custom header or token, and use SameSite.

Your mission

Defend a form you built

~35 min

Quick check

Which change best protects a cookie-based login from CSRF?

Go deeper

  1. 1Learn how a CSRF attack works step by step, from a crafted malicious link or form.
  2. 2Understand why anti-CSRF tokens (unique per session/request) are the standard defense.
  3. 3Research the SameSite cookie attribute as a modern, complementary defense.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge