๐Ÿš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
๐ŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
JS MASTER CLASS /// MASTER THE ENGINE /// BUILD LOGIC /// ASYNC PATTERNS /// JS MASTER CLASS /// MASTER THE ENGINE ///

HTML Sanitization | JavaScript Tutorial - In-Depth Guide

Master HTML sanitization: why hand-rolled regex-based sanitization always fails, using an established sanitization library with an allow-list configuration, and the emerging native sanitizer API.

โšก Total XP: 0|๐Ÿ’ป html XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core logic.

Quick Quiz //

Is a hand-written regex-based HTML filter a reliable way to prevent XSS?


๐Ÿš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
๐ŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

When you genuinely need to render user-supplied HTML (like formatted rich-text comments), sanitization strips dangerous elements and attributes while preserving safe formatting โ€” a fundamentally different (and more robust) approach than trying to hand-write your own escaping logic.

1HTML Sanitization | JavaScript Tutorial - In-Depth Guide Part 1

Sanitization parses untrusted HTML and removes anything dangerous (script tags, event handler attributes, javascript: URLs) while preserving safe formatting elements like <b>, <i>, and <a>.

โœ•
โ€”
+
const dirty = '<p>Hello <script>evil()</script><b>world</b></p>';
const clean = sanitize(dirty);
// '<p>Hello <b>world</b></p>' โ€” script removed, safe formatting kept
localhost:3000
๐Ÿงผ

Safely Allowing Rich Content

2HTML Sanitization | JavaScript Tutorial - In-Depth Guide Part 2

Never attempt to write your own HTML sanitizer using regular expressions โ€” HTML parsing has enormous edge cases and encoding tricks that make regex-based filtering reliably bypassable by a determined attacker.

โœ•
โ€”
+
// DON'T do this โ€” regex-based sanitization is notoriously bypassable:
const broken = html.replace(/<script.*?<\/script>/gi, '');
// Easily bypassed with e.g. <scr<script>ipt> or event handler attributes
localhost:3000

Never Hand-Roll Sanitization with Regex

3HTML Sanitization | JavaScript Tutorial - In-Depth Guide Part 3

An established sanitization library (like DOMPurify) parses the HTML with a real HTML parser and removes anything not on an explicit allow-list of safe tags and attributes.

โœ•
โ€”
+
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(userSuppliedHtml);
element.innerHTML = clean; // now safe to insert
localhost:3000

Using an Established Library

4HTML Sanitization | JavaScript Tutorial - In-Depth Guide Part 4

Configure the sanitizer with an explicit allow-list of exactly which tags and attributes are permitted for your specific use case โ€” the more restrictive the allow-list, the smaller the attack surface.

โœ•
โ€”
+
const clean = DOMPurify.sanitize(userHtml, {
  ALLOWED_TAGS: ['b', 'i', 'a', 'p'],
  ALLOWED_ATTR: ['href'],
});
localhost:3000

Configuring an Allow-List

5HTML Sanitization | JavaScript Tutorial - In-Depth Guide Part 5

Sanitize on the SERVER before storing user content whenever possible, in addition to (not instead of) sanitizing again on the client before rendering โ€” defense in depth against any single point of failure.

โœ•
โ€”
+
// Server: sanitize before storing
const safeToStore = sanitizeOnServer(userSubmittedHtml);
db.save({ comment: safeToStore });

// Client: sanitize again before rendering, as defense in depth
el.innerHTML = DOMPurify.sanitize(fetchedComment);
localhost:3000

Defense in Depth

6Step-by-Step Breakdown

Sanitization parses untrusted HTML and removes anything dangerous (script tags, event handler attributes, javascript: URLs) while preserving safe formatting elements like <b>, <i>, and <a>.

Never attempt to write your own HTML sanitizer using regular expressions โ€” HTML parsing has enormous edge cases and encoding tricks that make regex-based filtering reliably bypassable by a determined attacker.

Checkpoint: Is a hand-written regex-based HTML filter a reliable way to prevent XSS?

  • โ†’Yes, regex can reliably catch all dangerous HTML
  • โ†’No, HTML parsing edge cases make regex-based filtering bypassable

An established sanitization library (like DOMPurify) parses the HTML with a real HTML parser and removes anything not on an explicit allow-list of safe tags and attributes.

Configure the sanitizer with an explicit allow-list of exactly which tags and attributes are permitted for your specific use case โ€” the more restrictive the allow-list, the smaller the attack surface.

Sanitize on the SERVER before storing user content whenever possible, in addition to (not instead of) sanitizing again on the client before rendering โ€” defense in depth against any single point of failure.

Checkpoint: Is client-side-only sanitization (with no server-side sanitization) sufficient defense in depth?

  • โ†’Yes, client-side sanitization alone is always enough
  • โ†’No, other consumers of the stored data may not re-sanitize

Next, we'll explore 'Content Security Policy Basics'.

Level Up ๐Ÿš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1A Well-Configured Sanitizer Preserves Semantic HTML Needed for Accessibility

Allowing genuinely meaningful structural tags (like <strong>, <em>, and properly-attributed <a>) through the sanitizer, rather than stripping all HTML down to plain text, preserves the semantic cues assistive technology relies on to convey emphasis and interactivity correctly.

SEO Implications

  • 1

    Sanitization Prevents Spam/Malware Injection into Indexed User-Generated Content

    Properly sanitizing user-generated content (comments, reviews, forum posts) prevents attackers from injecting hidden spam links or malicious redirects that search engines could penalize the site for, protecting the domain's search reputation.

Best Practices

Always Use an Established, Actively-Maintained Sanitization Library

Real HTML parsing and a continuously-updated understanding of new bypass techniques are things only a dedicated, battle-tested library can reliably provide.

Configure the Tightest Allow-List Your Actual Use Case Requires

Only permitting the specific tags and attributes your feature genuinely needs (rather than a broad default) minimizes the residual attack surface even after sanitization.

Frequent Bugs

THE BUG

Writing a custom regex to strip <script> tags, which an attacker bypasses using an alternative XSS vector like an `<img onerror=...>` tag or encoded characters the regex doesn't account for.

THE FIX

Replace any custom regex-based filtering with an established sanitization library that uses a real HTML parser and allow-list.

THE BUG

Sanitizing user content only when it is first submitted, but never re-sanitizing when rendering it later, missing protection if the storage layer itself is ever compromised or bypassed by another code path.

THE FIX

Sanitize both when storing data and again immediately before rendering it, as independent, defense-in-depth layers.

Real-World Examples

Allowing Rich-Text Formatting in Blog Comments

A blog wanted to let commenters use basic formatting (bold, italic, links) without exposing the site to script injection.

import DOMPurify from 'dompurify';

function renderComment(rawHtml) {
  const clean = DOMPurify.sanitize(rawHtml, {
    ALLOWED_TAGS: ['b', 'i', 'a'],
    ALLOWED_ATTR: ['href'],
  });
  commentEl.innerHTML = clean;
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Using a custom regex to strip dangerous HTML

const clean = DOMPurify.sanitize(dirtyHtml);

The Solution //

Replace with an established sanitization library that uses a real HTML parser.

Lesson Glossary

[01]HTML Sanitization

Parsing untrusted HTML and removing dangerous elements/attributes while preserving safe formatting.

Code Preview
DOMPurify.sanitize()

[02]Allow-List

An explicit list of permitted tags/attributes a sanitizer keeps, discarding everything else.

Code Preview
ALLOWED_TAGS

[03]DOMPurify

A widely-used, actively-maintained JavaScript HTML sanitization library.

Code Preview
import DOMPurify from 'dompurify'

[04]Defense in Depth

Applying security measures at multiple layers (server AND client) rather than relying on just one.

Code Preview
sanitize server + client

[05]Regex-Based Sanitization (Anti-Pattern)

A discouraged approach to filtering HTML using string pattern matching, known to be bypassable.

Code Preview
html.replace(/<script>/, ...)

Continue Learning