feat(notification): Input sanitization and XSS protection for rich-text template fields (#611)#652
Open
jadonamite wants to merge 1 commit into
Open
Conversation
…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
|
@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! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.ts—HTMLSanitizerServicewrapping 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 forcesrel="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') plusX-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— addsdompurify,jsdom,@types/jsdom.Acceptance criteria
script-src 'self',object-src 'none'Closes #611