Skip to content
intermediatePhase 41 · Frontend Security

XSS

Understand Cross-Site Scripting attacks and prevention strategies.

45m
0 problems
Topic Progress0%

XSS Attack Types

XSS Attack Types

1. Stored XSS

Malicious script stored on server, executed when viewed.

// Vulnerable: User comment
const comment = '<img src=x onerror="alert(1)">';
element.innerHTML = comment; // Executes script

// Safe: Use textContent
element.textContent = comment; // Shows as text

2. Reflected XSS

Script in URL or request, reflected back unescaped.

// Vulnerable: URL parameter
const params = new URLSearchParams(window.location.search);
const name = params.get('name');
element.innerHTML = `Hello ${name}`; // Executes script

// Safe: Sanitize input
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(name);

3. DOM-based XSS

Script modifies DOM directly via JavaScript.

// Vulnerable: Using document.write
document.write('<h1>' + userInput + '</h1>');

// Vulnerable: Using innerHTML
element.innerHTML = userInput;

// Vulnerable: Using eval
eval(userInput);

// Safe alternatives
element.textContent = userInput; // Safe
element.innerText = userInput; // Safe

Common XSS Vectors

// Script tags
<script>alert(1)</script>

// Event handlers
<img src=x onerror="alert(1)">
<svg onload="alert(1)">

// JavaScript URLs
javascript:alert(1)

// Data URLs
data:text/html,<script>alert(1)</script>

React-Specific Risks

// Vulnerable: dangerouslySetInnerHTML
function Comment({ html }) {
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}

// Safe: Use textContent
function Comment({ text }) {
  return <div>{text}</div>;
}

// Safe: Sanitize before using dangerouslySetInnerHTML
import DOMPurify from 'dompurify';

function Comment({ html }) {
  const clean = DOMPurify.sanitize(html);
  return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}

Input Sanitization

Input Sanitization

Client-side Sanitization

import DOMPurify from 'dompurify';

// Sanitize HTML
const clean = DOMPurify.sanitize(userInput);

// Configure DOMPurify
const clean = DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong'],
  ALLOWED_ATTR: [],
});

// Allow specific tags
const clean = DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: ['p', 'br', 'b', 'i'],
});

Server-side Sanitization

import validator from 'validator';
import sanitizeHtml from 'sanitize-html';

// Email validation
const email = validator.normalizeEmail(userInput);

// Sanitize HTML
const clean = sanitizeHtml(userInput, {
  allowedTags: ['b', 'i', 'em', 'strong', 'a'],
  allowedAttributes: {
    'a': ['href'],
  },
  allowedSchemes: ['https', 'mailto'],
});

Input Validation

// Validate against schema
import { z } from 'zod';

const userSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(0).max(150),
});

try {
  const user = userSchema.parse(userInput);
} catch (error) {
  // Invalid input
}

Output Encoding

// HTML entity encoding
function escapeHtml(str) {
  const map = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;',
  };
  return str.replace(/[&<>"']/g, char => map[char]);
}

// Use in templates
const safeHtml = `<div>${escapeHtml(userInput)}</div>`;

Content Security Policy

// CSP header
Content-Security-Policy: default-src 'self'; script-src 'self';

// Inline styles only
Content-Security-Policy: style-src 'self' 'unsafe-inline';

// No inline scripts
Content-Security-Policy: script-src 'self';

XSS Prevention

XSS Prevention

Use Framework Features

// React: Auto-escapes by default
function UserGreeting({ name }) {
  return <h1>Hello, {name}</h1>; // Safe
}

// React: Avoid dangerouslySetInnerHTML
// Only use with sanitized content

Set Secure Headers

// Content-Security-Policy
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';"
  );
  next();
});

// X-XSS-Protection
res.setHeader('X-XSS-Protection', '1; mode=block');

// X-Content-Type-Options
res.setHeader('X-Content-Type-Options', 'nosniff');

HttpOnly Cookies

// Set cookies as HttpOnly
res.cookie('session', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
});

Use Text Instead of HTML

// Vulnerable
element.innerHTML = userContent;

// Safe
element.textContent = userContent;
element.innerText = userContent;

// For rich text, use a sanitizer
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userContent);

Escape Dynamic Content

// In templates, escape user input
const template = `
  <div>
    <h1>${escapeHtml(title)}</h1>
    <p>${escapeHtml(content)}</p>
  </div>
`;

// In React, JSX auto-escapes
return (
  <div>
    <h1>{title}</h1>
    <p>{content}</p>
  </div>
);

Testing for XSS

// Test that user input is escaped
describe('XSS Prevention', () => {
  it('should escape HTML in user input', () => {
    const malicious = '<script>alert(1)</script>';
    render(<Comment text={malicious} />);

    expect(screen.getByText(malicious)).toBeInTheDocument();
    expect(screen.queryByText('alert(1)')).not.toBeInTheDocument();
  });
});

Practice Problems

0/3solved
Build Cross-Site Scripting (XSS) Component

Create a reusable React component implementing Cross-Site Scripting (XSS). Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Cross-Site Scripting (XSS) Testing

Write unit and integration tests for Cross-Site Scripting (XSS) using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Cross-Site Scripting (XSS) Performance

Optimize Cross-Site Scripting (XSS) for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What is Stored XSS?

Question 1 options

2. How does React prevent XSS?

Question 2 options

3. What is the primary purpose of Cross-Site Scripting (XSS)?

Question 3 options

4. What is a common mistake when implementing Cross-Site Scripting (XSS)?

Question 4 options

Flashcards

Question

What is XSS?

Answer

Cross-Site Scripting - injecting malicious scripts into web pages.

Question

What are the three types of XSS?

Answer

Stored, Reflected, and DOM-based XSS.

Question

How do you prevent XSS in React?

Answer

Avoid dangerouslySetInnerHTML, use textContent, sanitize HTML with DOMPurify.

Question

What is Content Security Policy?

Answer

An HTTP header that restricts which resources can be loaded and executed.

Question

What is Cross-Site Scripting (XSS)?

Answer

Cross-Site Scripting (XSS) is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.XSS allows attackers to inject malicious scripts
  • 2.Three types: Stored, Reflected, DOM-based
  • 3.React auto-escapes by default, avoid dangerouslySetInnerHTML
  • 4.Use DOMPurify to sanitize HTML content
  • 5.Set CSP headers to restrict script execution

Interview Tips

  • Explain the three types of XSS attacks
  • Discuss how React prevents XSS
  • Know how to sanitize user input

Cheat Sheet

XSS Prevention Cheat Sheet

Types

  1. Stored: Script stored on server
  2. Reflected: Script in URL/request
  3. DOM-based: Script modifies DOM

Prevention

  • Use textContent instead of innerHTML
  • Sanitize HTML with DOMPurify
  • Use React's auto-escaping
  • Set CSP headers
  • Use HttpOnly cookies

CSP Header

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

React Safe Pattern

// Safe
<div>{userInput}</div>

// Dangerous (sanitize first)
<div dangerouslySetInnerHTML={{__html: sanitized}} />