XSS vs CSRF, finally clarified

XSS runs code in your origin. CSRF rides your browser. Different threats, different defenses. Confusing them leads to half-applied fixes.

· LoginWith team

“XSS” and “CSRF” are the two acronyms every security report mentions and every junior dev confuses. They attack different things, they’re defended differently, and applying one’s defense to the other’s attack does nothing.

Cross-Site Scripting (XSS)

What it is: the attacker gets their JavaScript to run inside your origin. A comment that renders as HTML, a URL parameter reflected into the page, a server-side template that doesn’t escape — all vectors.

What it can do:

  • Read any cookie not marked HttpOnly
  • Read everything in localStorage and sessionStorage
  • Make authenticated requests as the user (cookies are sent automatically)
  • Read and modify the DOM, including keystrokes on a login form
  • Exfiltrate anything the user has access to

Defenses:

  • Escape all user content on output. Every framework has a safe default; don’t disable it.
  • Content-Security-Policy (CSP): restrict which scripts can run. A strict CSP (script-src 'self') turns most XSS into annoying noise instead of full compromise.
  • HttpOnly cookies: prevents XSS from stealing session cookies. Doesn’t prevent XSS from making requests using the cookie (but that’s a different threat).
  • No eval, no new Function, no innerHTML with user input.
  • Sanitize rich-text input server-side. DOMPurify on the client isn’t enough if an attacker can bypass the client.

Cross-Site Request Forgery (CSRF)

What it is: the attacker makes the victim’s browser send an authenticated request. The attacker never runs code on your site — they just construct a request that the victim’s browser automatically attaches cookies to.

What it can do:

  • Trigger any state-changing action the user has permission for (change email, transfer funds, post a comment)
  • Not read the response (same-origin policy blocks that)

Defenses:

  • SameSite=Lax or Strict cookies: the browser doesn’t attach the cookie to cross-site POSTs.
  • CSRF tokens: a per-form random value that the attacker can’t guess and doesn’t have access to cross-origin.
  • Origin/Referer check: for state-changing endpoints, verify the request came from your own origin.
  • Sec-Fetch-Site header: newer browsers indicate where the request originated. Reject cross-site on mutating endpoints.

The confusion

The classic mistake: “we have CSRF tokens, so we’re safe from XSS.” No. XSS runs in your origin, where it can read the CSRF token from the page and include it in forged requests. CSRF tokens protect against cross-site attackers, not in-origin attackers.

The inverse mistake: “we have HttpOnly cookies, so we don’t need CSRF tokens.” No. HttpOnly prevents XSS from reading the cookie, but CSRF doesn’t need to read it — the browser attaches it automatically. You still need SameSite or a token.

Different threats. Different defenses. Apply both.

Want auth that just works?

Get started with LoginWith