diff --git a/lib/__tests__/email-sanitization.test.ts b/lib/__tests__/email-sanitization.test.ts
index 1f9c2cb2..b2426a68 100644
--- a/lib/__tests__/email-sanitization.test.ts
+++ b/lib/__tests__/email-sanitization.test.ts
@@ -168,19 +168,32 @@ describe('email-sanitization', () => {
expect(sanitizeSignatureHtml(' ')).toBe('');
});
- it('should be stricter than email sanitization', () => {
- const html = '
Text
';
+ it('should be stricter than email sanitization for script-bearing tags', () => {
+ const html = 'Text
';
const emailClean = sanitizeEmailHtml(html);
const signatureClean = sanitizeSignatureHtml(html);
- // Email allows table
+ // Both preserve tables (signatures are universally table-based)
expect(emailClean).toContain('');
+ expect(signatureClean).toContain(' {
+ const signature = '';
+ const clean = sanitizeSignatureHtml(signature);
+ expect(clean).toContain('cellpadding');
+ expect(clean).toContain('cellspacing');
+ expect(clean).toContain('valign');
+ expect(clean).toContain('align');
+ expect(clean).toContain('bgcolor');
+ expect(clean).toContain('colspan');
+ });
});
describe('parseHtmlSafely', () => {
diff --git a/lib/email-sanitization.ts b/lib/email-sanitization.ts
index bee197f2..20145f55 100644
--- a/lib/email-sanitization.ts
+++ b/lib/email-sanitization.ts
@@ -58,11 +58,19 @@ export function sanitizeEmailHtmlForIframe(html: string): string {
/**
* Sanitize HTML signature with stricter rules
- * Allows basic formatting plus
for company logos
+ * Allows basic formatting plus
for company logos, plus table-based
+ * layouts (the de-facto standard for email signatures).
*/
export const SIGNATURE_SANITIZE_CONFIG = {
- ALLOWED_TAGS: ['p', 'br', 'b', 'strong', 'i', 'em', 'u', 'a', 'span', 'div', 'img'],
- ALLOWED_ATTR: ['href', 'style', 'class', 'src', 'alt', 'width', 'height', 'title'],
+ ALLOWED_TAGS: [
+ 'p', 'br', 'b', 'strong', 'i', 'em', 'u', 'a', 'span', 'div', 'img',
+ 'table', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th',
+ ],
+ ALLOWED_ATTR: [
+ 'href', 'style', 'class', 'src', 'alt', 'width', 'height', 'title',
+ 'cellpadding', 'cellspacing', 'border', 'valign', 'align', 'bgcolor',
+ 'colspan', 'rowspan',
+ ],
ALLOW_DATA_ATTR: false,
FORBID_TAGS: ['script', 'iframe', 'object', 'embed', 'video', 'audio'],
FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover'],