npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bernierllc/html-sanitizer

v1.0.7

Published

XSS prevention and HTML sanitization for user-generated content

Readme

@bernierllc/html-sanitizer

XSS Prevention and HTML Sanitization for User-Generated Content

A security-critical package that provides robust HTML sanitization to prevent XSS (Cross-Site Scripting) attacks in user-generated content. Built on battle-tested DOMPurify with configurable security profiles.

Installation

npm install @bernierllc/html-sanitizer

Quick Start

import { HtmlSanitizer, sanitizeHtml, SanitizationProfile } from '@bernierllc/html-sanitizer';

// Simple sanitization with defaults (MODERATE profile)
const clean = sanitizeHtml('<p>Safe content</p><script>alert("XSS")</script>');
// Result: '<p>Safe content</p>' (script removed)

// Get detailed sanitization report
const sanitizer = new HtmlSanitizer();
const result = sanitizer.sanitize(userHtml);

console.log(result.html);           // Clean HTML
console.log(result.modified);       // true if content was changed
console.log(result.removedTags);    // ['script', 'object']
console.log(result.xssPatterns);    // ['script tag', 'event handler']
console.log(result.warnings);       // Security warnings

Features

  • XSS Attack Prevention: Removes script tags, event handlers, dangerous protocols
  • Configurable Profiles: STRICT, MODERATE, RELAXED security levels
  • Custom Rules: Define your own allowed tags, attributes, and protocols
  • Security Reporting: Detailed reports of removed content and detected patterns
  • Performance Optimized: Built on DOMPurify, the industry standard
  • Zero-Config: Works out of the box with sensible defaults

Security Profiles

STRICT Profile

Only basic text formatting - ideal for comments or simple user input:

import { sanitizeWithProfile, SanitizationProfile } from '@bernierllc/html-sanitizer';

const clean = sanitizeWithProfile(userHtml, SanitizationProfile.STRICT);

Allowed:

  • Basic formatting: <p>, <br>, <strong>, <em>, <b>, <i>, <u>
  • Lists: <ul>, <ol>, <li>

Blocked:

  • Links, images, tables, media, everything else

MODERATE Profile (Default)

Standard blog content formatting - default for most use cases:

const sanitizer = new HtmlSanitizer(); // Uses MODERATE by default

Allowed:

  • All STRICT tags
  • Headings: <h1> through <h6>
  • Links: <a href="..." title="...">
  • Images: <img src="..." alt="...">
  • Code: <code>, <pre>, <blockquote>

Protocols: http, https, mailto

RELAXED Profile

Rich content for trusted users - includes tables and embedded media:

const clean = sanitizeWithProfile(userHtml, SanitizationProfile.RELAXED);

Allowed:

  • All MODERATE tags
  • Tables: <table>, <thead>, <tbody>, <tr>, <th>, <td>
  • Media: <iframe>, <video>, <audio>

Custom Configuration

Define your own security rules:

import { HtmlSanitizer } from '@bernierllc/html-sanitizer';

const sanitizer = new HtmlSanitizer({
  allowedTags: ['p', 'a', 'strong', 'em'],
  allowedAttributes: {
    'a': ['href', 'title']
  },
  allowedProtocols: ['https'], // Only HTTPS links
  allowStyles: false,
  allowDataUris: false
});

const result = sanitizer.sanitize(userHtml);

API Reference

HtmlSanitizer

Main class for HTML sanitization.

Constructor

new HtmlSanitizer(config?: SanitizerConfig)

Config Options:

  • allowedTags?: string[] - Whitelist of allowed HTML tags
  • allowedAttributes?: Record<string, string[]> - Allowed attributes per tag
  • allowedProtocols?: string[] - Allowed URL protocols
  • allowStyles?: boolean - Allow inline styles (default: false)
  • allowDataUris?: boolean - Allow data: URIs (default: false)
  • mode?: 'strict' | 'moderate' | 'relaxed' - Use predefined profile

Methods

sanitize(html: string): SanitizationResult

Sanitize HTML and get detailed report:

const result = sanitizer.sanitize(html);

// SanitizationResult:
{
  html: string;                              // Sanitized HTML
  modified: boolean;                         // Whether content was changed
  removedTags: string[];                     // Tags that were removed
  removedAttributes: Array<{                 // Attributes that were removed
    tag: string;
    attribute: string;
  }>;
  xssPatterns: string[];                     // XSS patterns detected
  warnings: string[];                        // Security warnings
}

sanitizeWithProfile(html: string, profile: SanitizationProfile): SanitizationResult

Sanitize using a specific profile:

const result = sanitizer.sanitizeWithProfile(html, SanitizationProfile.STRICT);

validate(html: string): ValidationResult

Check if HTML is safe without modifying:

const result = sanitizer.validate(html);

// ValidationResult:
{
  safe: boolean;      // Whether HTML is safe
  issues: string[];   // List of security issues
}

Convenience Functions

sanitizeHtml(html: string, config?: SanitizerConfig): string

Quick sanitization, returns clean HTML string:

import { sanitizeHtml } from '@bernierllc/html-sanitizer';

const clean = sanitizeHtml(userInput);

sanitizeWithProfile(html: string, profile: SanitizationProfile): string

Sanitize with a profile, returns clean HTML string:

import { sanitizeWithProfile, SanitizationProfile } from '@bernierllc/html-sanitizer';

const clean = sanitizeWithProfile(userInput, SanitizationProfile.STRICT);

validateHtml(html: string): { safe: boolean; issues: string[] }

Validate HTML safety:

import { validateHtml } from '@bernierllc/html-sanitizer';

const result = validateHtml(userInput);
if (!result.safe) {
  console.error('Unsafe HTML:', result.issues);
}

XSS Attack Prevention

This package protects against all common XSS attack vectors:

Script Tags

const html = '<p>Hello</p><script>alert("XSS")</script>';
const result = sanitizer.sanitize(html);

// result.html: '<p>Hello</p>'
// result.removedTags: ['script']
// result.xssPatterns: ['script tag']
// result.warnings: ['CRITICAL: Dangerous executable content removed']

Event Handlers

const html = '<img src="x" onerror="alert(1)">';
const result = sanitizer.sanitize(html);

// onerror attribute removed
// result.xssPatterns: ['event handler']

JavaScript Protocol

const html = '<a href="javascript:alert(1)">Click</a>';
const result = sanitizer.sanitize(html);

// javascript: protocol removed
// result.xssPatterns: ['javascript: protocol']

Data URIs

const html = '<img src="data:text/html,<script>alert(1)</script>">';
const result = sanitizer.sanitize(html);

// Detected and blocked
// result.xssPatterns: ['data: URI']

Embedded Objects

const html = '<object data="malicious.swf"></object>';
const result = sanitizer.sanitize(html);

// <object> and <embed> tags always removed
// result.removedTags: ['object']

Security Best Practices

Always Sanitize User Input

// ✅ CORRECT
app.post('/comment', (req, res) => {
  const sanitized = sanitizeHtml(req.body.comment);
  await saveComment(sanitized);
});

// ❌ WRONG - Never trust user input
app.post('/comment', (req, res) => {
  await saveComment(req.body.comment); // Dangerous!
});

Choose the Right Profile

// Comments: Use STRICT
const comment = sanitizeWithProfile(userComment, SanitizationProfile.STRICT);

// Blog posts: Use MODERATE (default)
const blogPost = sanitizeHtml(userBlogPost);

// Admin content: Use RELAXED (only for trusted users)
if (user.isAdmin) {
  const adminContent = sanitizeWithProfile(userContent, SanitizationProfile.RELAXED);
}

Monitor Security Events

const result = sanitizer.sanitize(userHtml);

if (result.xssPatterns.length > 0) {
  // Log security event
  logger.warn('XSS attempt detected', {
    userId: user.id,
    patterns: result.xssPatterns,
    removedTags: result.removedTags
  });
}

Use Validation Before Saving

const validation = validateHtml(userInput);

if (!validation.safe) {
  return res.status(400).json({
    error: 'Content contains unsafe HTML',
    issues: validation.issues
  });
}

Performance

  • Typical blog post (5KB): <10ms
  • Large content (500KB): <100ms
  • Memory usage: <50MB for large content

Built on DOMPurify, which is highly optimized and used by millions of websites.

Integration Status

Logger Integration

Status: Optional (recommended for security monitoring)

Justification: While this package can function without logging, it's highly recommended to integrate @bernierllc/logger for security event monitoring. The sanitizer can detect and remove XSS patterns, and logging these events helps with security auditing and threat detection. However, the package is designed to work without logging for environments where logging isn't available.

Pattern: Optional integration - package works without logger, but logger enhances security monitoring capabilities.

Example Integration:

import { Logger } from '@bernierllc/logger';
import { HtmlSanitizer } from '@bernierllc/html-sanitizer';

const logger = new Logger({ service: 'html-sanitizer' });
const sanitizer = new HtmlSanitizer();

const result = sanitizer.sanitize(userHtml);
if (result.xssPatterns.length > 0) {
  logger.warn('XSS attempt detected', {
    patterns: result.xssPatterns,
    removedTags: result.removedTags
  });
}

NeverHub Integration

Status: Not applicable

Justification: This is a core utility package that performs HTML sanitization. It does not participate in service discovery, event publishing, or service mesh operations. While security events could theoretically be published to NeverHub, this package focuses solely on sanitization logic and delegates event handling to calling code.

Pattern: Core utility - no service mesh integration needed. Security events should be handled by the application layer that uses this sanitizer.

Docs-Suite Integration

Status: Ready

Format: TypeDoc-compatible JSDoc comments are included throughout the source code. All public APIs are documented with examples and type information.

Dependencies

  • dompurify (^3.1.7) - HTML sanitization engine
  • jsdom (^25.0.1) - DOM implementation for Node.js

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build package
npm run build

# Lint code
npm run lint

Testing

This package has comprehensive test coverage (90%+) including:

  • XSS attack prevention (script tags, event handlers, protocols)
  • All security profiles (strict, moderate, relaxed)
  • Custom configuration options
  • Edge cases (malformed HTML, Unicode, large input)
  • Sanitization result metadata

Related Packages

Dependencies

  • dompurify (npm) - HTML sanitization engine
  • jsdom (npm) - DOM implementation

Used By

  • @bernierllc/content-transformer - Content format conversions
  • @bernierllc/content-editor-service - Editor backend
  • @bernierllc/markdown-renderer - HTML output sanitization

Part Of

  • Content Management Suite - Blog content and commit message workflows

License

Copyright (c) 2025 Bernier LLC

This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.

Security

For security concerns or to report vulnerabilities, please contact: [email protected]

This is a security-critical package. All XSS vulnerabilities are treated as high priority.