What is XSS and how do you prevent it?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
XSS is when attacker-supplied text ends up being executed as code in another user's browser. Because it runs on your origin, it can read cookies not marked HttpOnly, read localStorage, call your API as the victim, and rewrite the page.
el.innerHTML = "Hello " + userName;
// userName = '<img src=x onerror="steal(document.cookie)">'
The three kinds
- Stored — the payload is saved server-side (a comment, a profile field) and served to everyone. The most damaging.
- Reflected — it comes from the request, usually a query parameter echoed into the page, and is delivered by a crafted link.
- DOM-based — no server involvement; client code reads
location.hashor similar and writes it into the DOM.
The core defence: escape on output
The problem is not input, it is where the value is inserted. Escaping depends on context:
el.textContent = userName; // safe — always prefer this
el.setAttribute("title", value); // safe
el.innerHTML = userName; // unsafe
Frameworks escape by default — React, Vue and Svelte all do — so most XSS in modern apps comes through the explicit escape hatches: dangerouslySetInnerHTML, v-html, {@html}. Treat those as requiring the same care as raw innerHTML, and sanitise with DOMPurify when you genuinely must render HTML.
Also dangerous
javascript: in an href, user-controlled src on a script, eval and new Function on any string that touched user input.
Defence in depth
A Content-Security-Policy with a nonce stops injected scripts running even if one slips through — this is the single most valuable header you can add. Mark session cookies HttpOnly so a successful XSS cannot steal them. Validate input as well, but treat that as narrowing the surface, not as the fix: the fix is correct escaping at every output point.
