Skip to content
intermediatePhase 41 · Frontend Security

Input Sanitization

Validate and sanitize user input to prevent injection attacks.

30m
0 problems
Topic Progress0%

Input Validation

Input Validation

Client-side Validation

// HTML5 validation
<input type="email" required />
<input type="number" min="0" max="100" />
<input type="text" pattern="[A-Za-z]{3}" />

// React validation
function validateEmail(email) {
  const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
  return re.test(email);
}

// Zod 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),
  password: z.string().min(8).max(100),
});

Server-side Validation

// Express with Joi
const Joi = require('joi');

const schema = Joi.object({
  name: Joi.string().min(1).max(100).required(),
  email: Joi.string().email().required(),
  age: Joi.number().integer().min(0).max(150),
});

app.post('/user', (req, res) => {
  const { error, value } = schema.validate(req.body);
  if (error) {
    return res.status(400).json({ error: error.details });
  }
  // Process valid data
});

// Express with express-validator
const { body, validationResult } = require('express-validator');

app.post('/user',
  body('email').isEmail(),
  body('password').isLength({ min: 8 }),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
  }
);

Whitelist Validation

// Only allow specific values
function validateStatus(status) {
  const allowed = ['active', 'inactive', 'pending'];
  return allowed.includes(status);
}

// Only allow specific characters
function validateUsername(username) {
  return /^[a-zA-Z0-9_]+$/.test(username);
}

// Only allow specific types
function validateAge(age) {
  return Number.isInteger(age) && age >= 0 && age <= 150;
}

Output Encoding

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>`;

URL Encoding

function encodeUrl(str) {
  return encodeURIComponent(str);
}

// Safe URL construction
const safeUrl = `https://example.com/search?q=${encodeUrl(userInput)}`;

// Or use URL API
const url = new URL('https://example.com/search');
url.searchParams.set('q', userInput);

JavaScript String Encoding

function escapeJs(str) {
  return str
n    .replace(/\\/g, '\\\\\')
    .replace(/'/g, "\\\'")
    .replace(/"/g, '\\"')
    .replace(/\n/g, '\\n')
    .replace(/\r/g, '\\r')
    .replace(/\t/g, '\\t');
}

// Safe in script tag
const script = `<script>var data = "${escapeJs(userInput)}";</script>`;

CSS Encoding

function escapeCss(str) {
  return str.replace(/[^a-zA-Z0-9-]/g, '\\\$&');
}

// Safe in style
const style = `div::before { content: "${escapeCss(userInput)}"; }`;

React Auto-escaping

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

// Avoid dangerouslySetInnerHTML
// Only use with sanitized content
import DOMPurify from 'dompurify';

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

Sanitization Libraries

Sanitization Libraries

DOMPurify

import DOMPurify from 'dompurify';

// Basic sanitization
const clean = DOMPurify.sanitize(userInput);

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

// For React
import DOMPurify from 'dompurify';

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

Validator.js

import validator from 'validator';

// Email
validator.isEmail('test@example.com'); // true

// URL
validator.isURL('https://example.com'); // true

// Alphanumeric
validator.isAlphanumeric('abc123'); // true

// Strong password
validator.isStrongPassword('P@ssw0rd'); // true

// Sanitize
validator.trim('  hello  '); // 'hello'
validator.escape('<script>'); // '&lt;script&gt;'

sanitize-html

import sanitizeHtml from 'sanitize-html';

// Basic sanitization
const clean = sanitizeHtml(userInput);

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

// Custom allowed tags
const clean = sanitizeHtml(userInput, {
  allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']),
  allowedAttributes: {
    ...sanitizeHtml.defaults.allowedAttributes,
    'img': ['src', 'alt', 'title'],
  },
});

Best Practices

  1. Validate on both client and server
  2. Use whitelist validation
  3. Sanitize HTML output with DOMPurify
  4. Encode output based on context
  5. Use framework auto-escaping
  6. Don't trust user input
  7. Test with malicious input
  8. Use Content Security Policy

Testing Sanitization

describe('Input Sanitization', () => {
  it('should sanitize HTML input', () => {
    const malicious = '<script>alert(1)</script>';
    const clean = DOMPurify.sanitize(malicious);
    expect(clean).not.toContain('<script>');
  });

  it('should validate email format', () => {
    expect(validator.isEmail('test@example.com')).toBe(true);
    expect(validator.isEmail('invalid')).toBe(false);
  });

  it('should escape HTML entities', () => {
    const input = '<script>alert(1)</script>';
    const escaped = escapeHtml(input);
    expect(escaped).toContain('&lt;script&gt;');
  });
});

Practice Problems

0/3solved
Build Input Sanitization Component

Create a reusable React component implementing Input Sanitization. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Input Sanitization Testing

Write unit and integration tests for Input Sanitization using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Input Sanitization Performance

Optimize Input Sanitization 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 input sanitization?

Question 1 options

2. Why validate on both client and server?

Question 2 options

3. What is the primary purpose of Input Sanitization?

Question 3 options

4. What is a common mistake when implementing Input Sanitization?

Question 4 options

Flashcards

Question

What is input sanitization?

Answer

Removing or encoding dangerous content from user input to prevent attacks.

Question

What is whitelist validation?

Answer

Only allowing known-good values instead of trying to block bad ones.

Question

What is HTML entity encoding?

Answer

Converting <, >, &, ", ' to their HTML entity equivalents.

Question

Why use DOMPurify?

Answer

To safely sanitize HTML content and prevent XSS attacks.

Question

What is Input Sanitization?

Answer

Input Sanitization is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.Always validate on both client and server
  • 2.Use whitelist validation when possible
  • 3.Sanitize HTML with DOMPurify
  • 4.Encode output based on context
  • 5.Don't trust user input

Interview Tips

  • Explain client vs server validation
  • Discuss output encoding techniques
  • Know sanitization libraries and when to use them

Cheat Sheet

Input Sanitization Cheat Sheet

Validation

  • Client-side: UX, can be bypassed
  • Server-side: Security, mandatory
  • Whitelist: Allow known-good values

Encoding

  • HTML: escapeHtml()
  • URL: encodeURIComponent()
  • JavaScript: escapeJs()
  • CSS: escapeCss()

Libraries

  • DOMPurify: HTML sanitization
  • validator.js: Input validation
  • sanitize-html: HTML sanitization

React

  • Auto-escapes by default
  • Avoid dangerouslySetInnerHTML
  • Use DOMPurify if needed

Best Practices

  • Validate both sides
  • Use whitelists
  • Sanitize HTML output
  • Test with malicious input