NeahNew/lib/utils/dom-purify-config.ts
2025-05-03 14:17:46 +02:00

81 lines
3.1 KiB
TypeScript

/**
* CENTRALIZED DOMPURIFY CONFIGURATION
*
* This file provides a consistent, centralized configuration for DOMPurify
* used throughout the application. All components that need to sanitize HTML
* should import from this file instead of configuring DOMPurify directly.
*/
import DOMPurify from 'isomorphic-dompurify';
// Reset any existing hooks to start with a clean slate
DOMPurify.removeAllHooks();
// Configure DOMPurify with settings appropriate for email content
DOMPurify.setConfig({
ADD_TAGS: [
'html', 'head', 'body', 'style', 'link', 'meta', 'title',
'table', 'caption', 'col', 'colgroup', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th',
'div', 'span', 'img', 'br', 'hr', 'section', 'article', 'header', 'footer',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote', 'pre', 'code',
'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'a', 'b', 'i', 'u', 'em',
'strong', 'del', 'ins', 'mark', 'small', 'sub', 'sup', 'q', 'abbr',
'font' // Allow legacy font tag often found in emails
],
ADD_ATTR: [
'style', 'class', 'id', 'name', 'href', 'src', 'alt', 'title', 'width', 'height',
'border', 'cellspacing', 'cellpadding', 'bgcolor', 'background', 'color',
'align', 'valign', 'dir', 'lang', 'target', 'rel', 'charset', 'media',
'colspan', 'rowspan', 'scope', 'span', 'size', 'face', 'hspace', 'vspace',
'data-*',
'start', 'type', 'value', 'cite', 'datetime', 'wrap', 'summary'
],
KEEP_CONTENT: true,
WHOLE_DOCUMENT: false,
ALLOW_DATA_ATTR: true,
ALLOW_UNKNOWN_PROTOCOLS: true, // Needed for some email clients
FORBID_TAGS: ['script', 'iframe', 'object', 'embed', 'form', 'input', 'button', 'select', 'textarea'],
FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover', 'onmouseout'],
FORCE_BODY: false,
USE_PROFILES: { html: true } // Use HTML profile for more permissive sanitization for emails
});
/**
* Sanitizes HTML content with the centralized DOMPurify configuration
* @param html HTML content to sanitize
* @returns Sanitized HTML
*/
export function sanitizeHtml(html: string): string {
if (!html) return '';
try {
// Use DOMPurify with our central configuration
const clean = DOMPurify.sanitize(html, {
ADD_ATTR: ['style', 'class', 'id', 'align', 'valign', 'colspan', 'rowspan', 'cellspacing', 'cellpadding', 'bgcolor']
});
// Fix common email rendering issues
const fixedHtml = clean
// Fix for Outlook WebVML content
.replace(/<!--\[if\s+gte\s+mso/g, '<!--[if gte mso')
// Fix for broken image paths that might be relative
.replace(/(src|background)="(?!http|data|https|cid)/gi, '$1="https://');
return fixedHtml;
} catch (e) {
console.error('Error sanitizing HTML:', e);
// Fall back to a basic sanitization approach
return html
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/on\w+="[^"]*"/g, '')
.replace(/(javascript|jscript|vbscript|mocha):/gi, 'removed:');
}
}
/**
* Get the configured DOMPurify instance
* Use this if you need to perform custom sanitization beyond the standard function
*/
export function getDOMPurify(): typeof DOMPurify {
return DOMPurify;
}