Skip to content

Commit 0d65c70

Browse files
Refactor HTML sanitization: replace DOMPurify with sanitize-html for improved security and maintainability
Fixes serverless Vercel support issue/crash Signed-off-by: Shahm Najeeb <Shahm_Najeeb@outlook.com>
1 parent e80b68e commit 0d65c70

6 files changed

Lines changed: 68 additions & 592 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ documentation.
2323
- No credentials exposed to client
2424
- Rate limiting on all endpoints
2525
- Comprehensive security headers
26-
- HTML sanitization with DOMPurify
26+
- HTML sanitization with sanitize-html
2727
- CSRF protection for state changes
2828

2929
## Quick Start
@@ -196,7 +196,7 @@ npm start
196196
- **Framework**: Next.js 16 (App Router)
197197
- **Authentication**: bcryptjs + JWT
198198
- **IMAP**: node-imap + mailparser
199-
- **Sanitization**: isomorphic-dompurify
199+
- **Sanitization**: sanitize-html
200200
- **UI**: React + Tailwind CSS + shadcn/ui
201201
- **TypeScript**: Full type safety
202202

SECURITY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ It provides **read-only** access to IMAP mailboxes through a secure web interfac
3131

3232
### Content Security
3333

34-
- **HTML sanitization** - All email HTML sanitized with DOMPurify before display
34+
- **HTML sanitization** - All email HTML sanitized with sanitize-html before display
3535
- **Allowed HTML tags whitelist** - Only safe formatting tags permitted
3636
- **Content Security Policy** - Strict CSP headers on all responses
3737
- **XSS protection** - Multiple layers prevent cross-site scripting

lib/imap-service.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import Imap from "imap"
1414
import {simpleParser} from "mailparser"
1515
import {getAccountById} from "./imap-config"
16-
import DOMPurify from "isomorphic-dompurify"
16+
import sanitizeHtml from "sanitize-html"
1717
import {EmailCount, EmailDetail, EmailFolder, GetAttachmentParams, GetEmailParams, ListEmailsParams} from "@/types";
1818
import {FolderSettings, ImapSettings} from "./settings"
1919

@@ -336,8 +336,8 @@ export async function getEmail(params: GetEmailParams): Promise<EmailDetail | nu
336336
if (attributes && parsed) {
337337
// Sanitize HTML to prevent XSS
338338
const sanitizedHtml = parsed.html
339-
? DOMPurify.sanitize(parsed.html, {
340-
ALLOWED_TAGS: [
339+
? sanitizeHtml(parsed.html, {
340+
allowedTags: [
341341
"p",
342342
"br",
343343
"strong",
@@ -357,7 +357,17 @@ export async function getEmail(params: GetEmailParams): Promise<EmailDetail | nu
357357
"tr",
358358
"td",
359359
"th",
360+
"tbody",
361+
"thead",
362+
"span",
363+
"div",
364+
"img",
360365
],
366+
allowedAttributes: {
367+
'a': ['href', 'name', 'target'],
368+
'img': ['src', 'alt', 'title', 'width', 'height'],
369+
},
370+
allowedSchemes: ['http', 'https', 'mailto'],
361371
})
362372
: undefined
363373

lib/settings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ export const EmailDisplaySettings = {
291291
* - Users can manually toggle between views if both exist
292292
*
293293
* Considerations:
294-
* - HTML: Better visual experience, potential XSS risks (mitigated by DOMPurify)
294+
* - HTML: Better visual experience, potential XSS risks (mitigated by sanitize-html)
295295
* - Text: Faster rendering, better for accessibility, more private
296296
*/
297297
defaultView: 'html' as 'html' | 'text',

0 commit comments

Comments
 (0)