Stop 20 · Advanced TopicsTopics · 14/14

Security (XSS, CSRF, CSP)

Part of the Frontend Developer Roadmap

In short

One unescaped comment box can let an attacker run code in every visitor's browser. Frontend security isn't only the backend's job, and three ideas cover a lot of the risk.

The core web security threats every frontend developer should understand — Cross-Site Scripting, Cross-Site Request Forgery, and Content Security Policy as a key mitigation.

The jaadu bank cashier checks a cheque with a magnifying glass near a guarded staff door.

Think of it like this

Bank branch safety rules

The bank checks every cheque's signature (CSRF protection), never cashes a note just because it says "pay me" (XSS), and only lets approved staff behind the counter (CSP). Your site needs the same three habits.

Watch it happen

Three attacks, three defences

Attacker
Your site
Victim

comment: <img onerror>

1/7An attacker posts a comment containing HTML that tries to run JavaScript.

The big ideas

What you need to know

XSS: injected scripts

Cross-Site Scripting happens when user input is run as HTML or JS on your page. React escapes text by default.

CSRF: forged requests

A malicious site tricks the browser into sending a logged-in request to yours. SameSite cookies and CSRF tokens stop it.

CSP: an allow list

A Content-Security-Policy header tells the browser which sources may load scripts, styles and more.

Protect the cookie

HttpOnly cookies can't be read by JavaScript, so even an XSS bug can't easily steal the session.

See it in code

Walk through the code

tsx
1// Bad: XSS risk: user text is treated as HTML2<div dangerouslySetInnerHTML={{ __html: comment.body }} />3 4// Good: React escapes plain text for you5<div>{comment.body}</div>6 7// Good: if you truly need HTML, sanitise it first8import DOMPurify from "dompurify";9<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(comment.body) }} />10 11// A strict CSP response header12// Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'

1/4Dangerous: the comment is treated as real HTML.

A comment containing a script tag runs in the first version and shows as plain text in the second. The CSP blocks scripts from other domains even if one slips in.

Save yourself the pain

Common mistakes

Oops

Storing the login token in localStorage because it's easy.

Do this instead

Any XSS bug can read localStorage. Prefer HttpOnly, Secure, SameSite cookies set by the server.

Oops

Adding 'unsafe-inline' to the CSP as soon as something breaks.

Do this instead

Move inline scripts into files, or use nonces. 'unsafe-inline' removes much of CSP's protection.

Your mission

Attack your own app (safely)

~30 min

Quick check

Which change most directly reduces the damage if an XSS bug steals data with JavaScript?

Go deeper

  1. 1Learn how XSS happens (unescaped user input rendered as HTML) and how React protects against it by default.
  2. 2Read how CSRF tokens prevent forged requests from other sites.
  3. 3Add a basic Content-Security-Policy header to a project and see what it blocks.

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