DOMPurify provides utility functions for validating attributes, checking browser support, and accessing information about the sanitization process. These utilities enable you to validate input before sanitization and understand what was modified during the process.
Validate whether specific attribute values are allowed for given tag and attribute combinations.
/**
* Check if an attribute value is valid for a given tag and attribute name
* Uses the current or default configuration for validation rules
* @param tag - HTML tag name (case insensitive)
* @param attr - Attribute name (case insensitive)
* @param value - Attribute value to validate
* @returns True if the attribute value is valid and would be kept during sanitization
*/
function isValidAttribute(tag: string, attr: string, value: string): boolean;Usage Examples:
import DOMPurify from "dompurify";
// Validate common attributes
const validHref = DOMPurify.isValidAttribute('a', 'href', 'https://example.com');
console.log(validHref); // true
const validScript = DOMPurify.isValidAttribute('img', 'onerror', 'alert(1)');
console.log(validScript); // false
const validData = DOMPurify.isValidAttribute('div', 'data-id', '123');
console.log(validData); // true (if ALLOW_DATA_ATTR is true)
// Validate with custom configuration
DOMPurify.setConfig({
ALLOW_DATA_ATTR: false,
FORBID_ATTR: ['onclick']
});
const dataAttr = DOMPurify.isValidAttribute('span', 'data-custom', 'value');
console.log(dataAttr); // false (data attributes disabled)
const clickAttr = DOMPurify.isValidAttribute('button', 'onclick', 'doSomething()');
console.log(clickAttr); // false (onclick forbidden)
// Validate before sanitization
function safeSanitize(html, customAttrs = []) {
// Pre-validate custom attributes
const doc = new DOMParser().parseFromString(html, 'text/html');
const elements = doc.querySelectorAll('*');
for (const element of elements) {
for (const attr of element.attributes) {
if (!DOMPurify.isValidAttribute(element.tagName, attr.name, attr.value)) {
console.warn(`Invalid attribute will be removed: ${element.tagName}[${attr.name}="${attr.value}"]`);
}
}
}
return DOMPurify.sanitize(html);
}Check whether the current environment supports DOMPurify functionality.
/**
* Indicates whether the current environment supports running DOMPurify
* Checks for required DOM APIs and browser features
*/
readonly isSupported: boolean;Usage Examples:
// Check support before using DOMPurify
if (DOMPurify.isSupported) {
const clean = DOMPurify.sanitize(dirtyHTML);
document.getElementById('content').innerHTML = clean;
} else {
console.error('DOMPurify is not supported in this environment');
// Fallback handling for unsupported environments
document.getElementById('content').textContent = 'Content cannot be displayed safely';
}
// Conditional feature usage
function initializeApp() {
if (!DOMPurify.isSupported) {
throw new Error('This application requires DOMPurify support');
}
// Safe to use DOMPurify features
setupContentSanitization();
}
// Environment-specific initialization
const initDOMPurify = () => {
if (typeof window !== 'undefined' && DOMPurify.isSupported) {
// Browser environment with support
return DOMPurify;
} else if (typeof global !== 'undefined') {
// Node.js environment - might need jsdom
const { JSDOM } = require('jsdom');
const window = new JSDOM('').window;
return DOMPurify(window);
} else {
throw new Error('Unsupported environment for DOMPurify');
}
};Access the current version of DOMPurify for compatibility checks and debugging.
/**
* Version string of the DOMPurify library
* Format: "major.minor.patch" (e.g., "3.2.6")
*/
readonly version: string;Usage Examples:
// Version logging and debugging
console.log(`Using DOMPurify version: ${DOMPurify.version}`);
// Version compatibility checking
function checkDOMPurifyVersion() {
const [major, minor, patch] = DOMPurify.version.split('.').map(Number);
if (major < 3) {
console.warn('DOMPurify version is outdated. Please upgrade to v3.x or higher.');
}
if (major === 3 && minor < 2) {
console.info('Consider upgrading to DOMPurify 3.2+ for latest security fixes.');
}
return { major, minor, patch };
}
// Feature detection based on version
function getFeatureSupport() {
const version = DOMPurify.version;
return {
trustedTypes: version >= '2.4.0',
shadowDOM: version >= '2.0.0',
customElements: version >= '2.3.0',
inPlace: version >= '2.4.0'
};
}
// Error reporting with version info
function reportError(error, context) {
const errorReport = {
error: error.message,
context,
dompurifyVersion: DOMPurify.version,
userAgent: navigator.userAgent,
timestamp: new Date().toISOString()
};
console.error('DOMPurify Error Report:', errorReport);
}Access information about elements and attributes removed during the last sanitization operation.
/**
* Array of elements and attributes that DOMPurify removed during the last sanitization
* Reset on each sanitize() call - contains only removals from the most recent operation
*/
readonly removed: Array<RemovedElement | RemovedAttribute>;
interface RemovedElement {
/**
* The DOM element that was removed from the document
*/
element: Node;
}
interface RemovedAttribute {
/**
* The attribute that was removed (null if attribute couldn't be accessed)
*/
attribute: Attr | null;
/**
* The element the attribute was removed from
*/
from: Node;
}Usage Examples:
// Track what was removed during sanitization
const maliciousHTML = `
<div onclick="alert('xss')" data-safe="ok">
<script>alert('xss')</script>
<p>Safe content</p>
</div>
`;
const clean = DOMPurify.sanitize(maliciousHTML);
// Examine what was removed
console.log('Removed items:', DOMPurify.removed);
DOMPurify.removed.forEach(item => {
if ('element' in item) {
console.log('Removed element:', item.element.nodeName);
if (item.element.textContent) {
console.log('Element content:', item.element.textContent);
}
} else if ('attribute' in item) {
console.log('Removed attribute:', item.attribute?.name, 'from', item.from.nodeName);
console.log('Attribute value:', item.attribute?.value);
}
});
// Logging function for sanitization analysis
function analyzeAndSanitize(html, description = '') {
console.log(`\n=== Sanitizing: ${description} ===`);
console.log('Input:', html);
const result = DOMPurify.sanitize(html);
console.log('Output:', result);
console.log('Removed count:', DOMPurify.removed.length);
if (DOMPurify.removed.length > 0) {
console.log('Removed items:');
DOMPurify.removed.forEach((item, index) => {
if ('element' in item) {
console.log(` ${index + 1}. Element: <${item.element.nodeName.toLowerCase()}>`);
} else {
console.log(` ${index + 1}. Attribute: ${item.attribute?.name} from <${item.from.nodeName.toLowerCase()}>`);
}
});
}
return result;
}
// Usage
analyzeAndSanitize('<img src="x" onerror="alert(1)">Safe image</img>', 'Malicious image');
analyzeAndSanitize('<div data-id="123" onclick="hack()">Content</div>', 'Mixed attributes');Type definitions for working with DOMPurify utilities and return values.
/**
* Window-like object interface for cross-platform compatibility
* Defines the minimum required properties for DOMPurify to function
*/
type WindowLike = Pick<typeof globalThis,
| 'DocumentFragment'
| 'HTMLTemplateElement'
| 'Node'
| 'Element'
| 'NodeFilter'
| 'NamedNodeMap'
| 'HTMLFormElement'
| 'DOMParser'
> & {
document?: Document;
MozNamedAttrMap?: typeof window.NamedNodeMap;
} & Pick<TrustedTypesWindow, 'trustedTypes'>;
/**
* DOMPurify constructor function type
* Creates new DOMPurify instance with custom window-like object
*/
interface DOMPurifyFactory {
(root?: WindowLike): DOMPurify;
}
/**
* Information about removed elements during sanitization
*/
interface RemovedElement {
element: Node;
}
/**
* Information about removed attributes during sanitization
*/
interface RemovedAttribute {
attribute: Attr | null;
from: Node;
}Usage Examples:
// Creating DOMPurify instance for Node.js
import { JSDOM } from 'jsdom';
import createDOMPurify from 'dompurify';
const window = new JSDOM('').window as unknown as WindowLike;
const DOMPurify = createDOMPurify(window);
// Type-safe removal analysis
function analyzeRemovals(removed: Array<RemovedElement | RemovedAttribute>) {
const elements: RemovedElement[] = [];
const attributes: RemovedAttribute[] = [];
removed.forEach(item => {
if ('element' in item) {
elements.push(item);
} else {
attributes.push(item);
}
});
return {
removedElements: elements.length,
removedAttributes: attributes.length,
details: { elements, attributes }
};
}
// Usage with type safety
const result = DOMPurify.sanitize(html);
const analysis = analyzeRemovals(DOMPurify.removed);
console.log(`Removed ${analysis.removedElements} elements and ${analysis.removedAttributes} attributes`);