Both are client-side attacks, but XSS runs code in the browser while CSRF rides the user's session.
| XSS | CSRF | |
|---|---|---|
| Full name | Cross-Site Scripting | Cross-Site Request Forgery |
| Attack type | Inject and execute JavaScript | Forge authenticated HTTP requests |
| What the attacker gets | Full control of the page — steal tokens, keylog, redirect | One action performed as the victim |
| Requires victim interaction? | Victim visits the vulnerable page | Victim visits the attacker's page |
| Attacker sees response? | Yes — the script runs in the victim's browser | No — blind request |
| Same-origin policy | Bypassed (script runs in the target's origin) | Enforced (attacker can't read the response) |
| Key defense | Output encoding, CSP | CSRF tokens, SameSite cookies |
XSS runs the attacker's code in the victim's browser, inside the target's origin. CSRF makes the victim's browser send a request the attacker chose, without being able to read the answer. XSS is a capability; CSRF is a single forged action. That asymmetry is why XSS defeats CSRF defenses and not the other way round.
Does attacker-controlled script execute in the target's origin? If yes, it's XSS, and the severity conversation is about what that script can reach — session tokens, the DOM, any authenticated endpoint. If the attack works entirely from a page on a different origin with no script running on the target, it's CSRF.
Can the attacker read the response? This is the cleanest discriminator. XSS can, because the code is executing inside the origin and the same-origin policy is on its side. CSRF cannot — the browser sends the request and attaches the cookies, but the attacker's page is blocked from reading what came back. Any report claiming CSRF that also claims data exfiltration is either describing something else or describing a CORS misconfiguration.
Is a token involved? CSRF is defeated by an unpredictable value the attacker's site cannot obtain. XSS is not, because code running in the origin can simply read the token out of the page before using it. This is the practical relationship between the two: XSS defeats every CSRF defense, which is why fixing XSS takes precedence and why "we have CSRF tokens" is not a mitigating factor in an XSS report.
The target application has an email-change endpoint that requires a POST with a CSRF token and the current password.
Via CSRF alone, the attack fails twice over. The attacker's page cannot obtain the token, because reading it would require a cross-origin read the browser refuses. Even with the token, the endpoint requires the current password, which the attacker doesn't have. This is what a reasonable implementation looks like — and it illustrates that CSRF exploitation depends entirely on the endpoint's design.
Via stored XSS, all of that collapses. The attacker's script is running in the origin, so it fetches the settings page, parses the CSRF token out of the DOM, and submits the change with the token attached. The password requirement is a real obstacle — but the script can also register a keylogger on the login form, or wait for the user to re-authenticate, or simply use the existing session to do whatever else the account permits. The account takeover may take a different route, but the CSRF control contributed nothing.
That's the hierarchy in one example: CSRF exploits one endpoint's missing check, XSS exploits the trust the browser places in the entire origin.
XSS: context-aware output encoding, a framework that escapes by default, Content Security Policy to raise the cost of injected script, trusted types to lock down DOM sinks, and sanitizing HTML with a maintained library rather than a hand-written filter. Cookie flags help contain it — HttpOnly keeps script from reading the session cookie — but containment is not prevention.
CSRF: synchronizer tokens, SameSite cookie attributes, origin and referer checks, and requiring a header that a simple cross-origin form cannot set. Since browsers adopted SameSite=Lax as a default, most of this class disappeared; what remains is GET-triggered state changes, cookies deliberately set to None, and non-cookie authentication schemes that SameSite never covered.
Useful test of your own understanding: a CSP will not stop CSRF (the request isn't script, and it originates from a page the policy doesn't govern), and a CSRF token will not stop XSS (the script reads it). Controls that sound adjacent are not interchangeable.
XSS reports fail most often on impact rather than proof. An alert box demonstrates execution; it doesn't demonstrate consequence. Show the chain — read a token, drive an authenticated state change, reach account takeover. Stored XSS on an authenticated page consistently pays well precisely because that chain is short.
CSRF reports fail most often on exploitability. Establish that the endpoint genuinely lacks protection under current browser defaults, that the action has real consequence, and that the cookie configuration actually permits the cross-site request — a POST endpoint protected by SameSite=Lax is not exploitable no matter how absent the token is. Full collections: XSS and CSRF.
It can do something strictly better. Script running in the origin reads the CSRF token and issues a fully legitimate request, so the attacker isn't forging anything — the CSRF defense is simply irrelevant. This is why XSS outranks CSRF in severity almost every time.
No, and the reasoning is worth being clear about: the token is in the page, and XSS executes in the page. Anything the browser can read, injected script can read.
Yes, but selectively. Look at GET-triggered state changes, cookies explicitly set to SameSite=None for cross-site integrations, bearer-token or Basic authentication that SameSite never covered, and method-override parameters that turn a permitted request into a forbidden one.
It stops script from reading that cookie, which removes one exfiltration path. The script still runs and can make authenticated requests using the cookie the browser attaches automatically. Containment, not prevention.
XSS. It subsumes CSRF's impact, defeats CSRF's defenses, and reaches data that CSRF structurally cannot.