0Pricing
Frontend Academy · Lesson

XSS Prevention: Output Encoding CSP

Understand reflected, stored, and DOM-based XSS, escape user-controlled output, avoid innerHTML with untrusted data, and add a Content Security Policy header.

XSS Prevention: Output Encoding CSP is a free Frontend Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is XSS?

Cross-Site Scripting happens when an attacker injects executable JavaScript into your page. The browser runs it with your origin's privileges — stealing cookies, hijacking sessions, defacing the page, redirecting to malware.

Three Flavours of XSS

Stored: malicious script saved in DB, served to every visitor. Reflected: input echoed back in the response (?q=<script>...). DOM-based: client-side JS writes untrusted data into the DOM.

The Root Cause: innerHTML with Untrusted Data

Using innerHTML (or v-html, dangerouslySetInnerHTML) with user-controlled strings is the #1 XSS vector.

// BAD: user input rendered as HTML
el.innerHTML = userComment;  // attacker submits <img onerror=alert(1)>

// Vue equivalent:
<div v-html="userComment"></div>  // same bug

// React equivalent:
<div dangerouslySetInnerHTML={{ __html: userComment }} />  // same bug

Output Encoding (The Safe Default)

Treat untrusted strings as text, not HTML. React, Vue, Angular, and Svelte all do this by default in {value} interpolation.

// SAFE: text content, not HTML
el.textContent = userComment;  // <script> shows as literal text

// React (auto-escaped):
<div>{userComment}</div>

// Vue (auto-escaped):
<div>{{ userComment }}</div>

Sanitising When You Must Render HTML

If you genuinely need to render user HTML (rich text editors), sanitise with DOMPurify — never roll your own regex sanitiser.

import DOMPurify from 'dompurify';

const clean = DOMPurify.sanitize(userHtml);
el.innerHTML = clean; // strips <script>, on* handlers, dangerous URLs

URL Validation

User-controlled URLs in href or src can trigger XSS via javascript: schemes.

// BAD:
<a href={userUrl}>Click</a>
// attacker submits: javascript:alert(1)

// GOOD: whitelist protocols:
function safeUrl(url) {
  if (!/^https?:\/\//.test(url) && !url.startsWith('/')) return '#';
  return url;
}

Content Security Policy (CSP)

CSP is an HTTP response header that tells the browser which sources of script, style, image, etc. are allowed. Even if an attacker injects script, the browser refuses to run it.

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.trusted.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:

Strict CSP with Nonces

For inline scripts you control, use a per-request nonce. Attacker-injected scripts won't have the matching nonce.

// Server generates a random nonce per request:
const nonce = crypto.randomBytes(16).toString('base64');
res.setHeader('Content-Security-Policy', `script-src 'nonce-${nonce}' 'strict-dynamic'`);

// Inject into the HTML:
<script nonce="abc123">/* trusted inline code */</script>

HttpOnly + Secure Cookies

Set session cookies with HttpOnly so JavaScript can't read them — even if XSS happens, the attacker can't grab the session token.

Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Strict

Subresource Integrity (SRI)

When loading third-party scripts via CDN, use SRI to verify the content matches a hash. Compromised CDN can't serve malicious script without breaking the hash check.

<script
  src="https://cdn.example.com/lib.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"
></script>

Trusted Types (Experimental)

Trusted Types is a browser feature (Chromium-based) that forces dangerous sinks (innerHTML) to receive a Trusted Type object — preventing strings from being inserted at all.

Testing for XSS

Try injecting <img src=x onerror=alert(1)> into every text input that gets rendered back. If you see an alert, you have an XSS bug. Use tools like OWASP ZAP for automated scans.

Quick Check

Why is React's {userInput} safe by default but dangerouslySetInnerHTML is not?

Recap: XSS Prevention

Default to text rendering (React's {x}, Vue's {{ x }} are safe). Sanitise with DOMPurify when rendering HTML. Whitelist URL protocols. CSP header (with nonces or 'strict-dynamic') blocks injected scripts. HttpOnly cookies prevent JS theft. SRI hashes for CDN scripts. Test inputs with classic payloads.

Frequently asked questions

Is the “XSS Prevention: Output Encoding CSP” lesson free?

Yes — the full text of “XSS Prevention: Output Encoding CSP” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.

What will I learn in “XSS Prevention: Output Encoding CSP”?

Understand reflected, stored, and DOM-based XSS, escape user-controlled output, avoid innerHTML with untrusted data, and add a Content Security Policy header. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Frontend Academy?

No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “XSS Prevention: Output Encoding CSP” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Frontend Academy lesson?

Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. XSS Prevention: Output Encoding CSP
  2. CSRF: SameSite Cookies and Tokens
  3. Content Security Policy: nonce and hash
  4. OAuth Flows from the Frontend
← Back to Frontend Academy