Skip to content

feat(notification): Input sanitization and XSS protection for rich-text template fields (#611)#652

Open
jadonamite wants to merge 1 commit into
Smartdevs17:mainfrom
jadonamite:feat/template-xss-sanitization
Open

feat(notification): Input sanitization and XSS protection for rich-text template fields (#611)#652
jadonamite wants to merge 1 commit into
Smartdevs17:mainfrom
jadonamite:feat/template-xss-sanitization

Conversation

@jadonamite

Copy link
Copy Markdown

Summary

Email and notification templates accept rich text containing HTML. Without sanitization, these fields are stored XSS vectors — a malicious admin can inject <script>, event handlers, javascript: URLs, or hostile SVGs that execute in other admins' browsers when a template is previewed or sent. This adds server-side sanitization on every rich-text input, a hardened CSP on the admin dashboard, and a back-scan job for content saved before sanitization existed.

Changes

  • backend/shared/sanitizer/htmlSanitizer.tsHTMLSanitizerService wrapping DOMPurify in a jsdom window. Enforces the allowlist, rejects non-http(s)/mailto protocols, strips SVG/MathML/script/iframe/object, removes inline event handlers, and forces rel="noreferrer noopener" + target="_blank" on links. Reports whether anything was stripped (used by the back-scan job).
  • backend/shared/middleware/cspMiddleware.ts — hardened CSP (script-src 'self', object-src 'none', base-uri 'self', frame-ancestors 'self') plus X-Content-Type-Options, X-Frame-Options, Referrer-Policy. Express and Next.js adapters provided.
  • backend/services/notification/templateService.ts — sanitizes the body on save, strips all HTML from subjects, and renders a sanitized preview before save. Stored body is always the sanitized output.
  • backend/services/notification/jobs/backScanTemplates.ts — idempotent cron that scans existing templates, quarantines any with unsafe content, and stores the sanitized body.
  • developer-portal/utils/securityHeaders.ts — applies the shared CSP to admin dashboard routes.
  • package.json — adds dompurify, jsdom, @types/jsdom.

Acceptance criteria

  • Server-side sanitization (DOMPurify via jsdom) on all rich-text inputs
  • Tag allowlist: p, span, a, img, table, tr, td, th, h1-h6, ul, ol, li, strong, em, br, hr
  • Attribute allowlist: href, src, alt, style, class, target (rel=noreferrer forced on links)
  • Protocol restriction: href only http:/https:/mailto: (javascript:/data:/vbscript: rejected)
  • SVGs stripped entirely
  • CSP headers on admin dashboard with script-src 'self', object-src 'none'
  • Template preview renders sanitized output before save
  • Edge case: back-scan job quarantines + sanitizes already-saved malicious templates

Closes #611

…rtdevs17#611)

Sanitize rich-text email/notification templates server-side so stored HTML
can never carry executable markup, with CSP defence-in-depth on the admin
dashboard.

- backend/shared/sanitizer: HTMLSanitizerService wrapping DOMPurify (via
  jsdom) with a strict tag/attribute allowlist, http/https/mailto-only href
  protocols, full SVG/script/iframe stripping, and forced rel=noreferrer on
  links.
- backend/shared/middleware/cspMiddleware.ts: hardened CSP
  (script-src 'self', object-src 'none') plus companion security headers,
  with Express and Next.js adapters.
- backend/services/notification/templateService.ts: sanitize body on save,
  strip HTML from subjects, and render a sanitized preview before save.
- backend/services/notification/jobs/backScanTemplates.ts: idempotent cron
  that quarantines and re-sanitizes pre-existing unsafe templates.
- developer-portal/utils/securityHeaders.ts: applies the shared CSP to admin
  dashboard routes.
- package.json: add dompurify, jsdom, @types/jsdom.

Closes Smartdevs17#611
@drips-wave

drips-wave Bot commented Jun 24, 2026

Copy link
Copy Markdown

@jadonamite Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add input sanitization and XSS protection for rich text template fields

1 participant