diff --git a/apps/api/src/app/message-template/shared/sanitizer.service.spec.ts b/apps/api/src/app/message-template/shared/sanitizer.service.spec.ts index 1af3d689648..e4b7b9d6a4f 100644 --- a/apps/api/src/app/message-template/shared/sanitizer.service.spec.ts +++ b/apps/api/src/app/message-template/shared/sanitizer.service.spec.ts @@ -24,4 +24,40 @@ describe('HTML Sanitizer', function () { ]); expect(result[0].content).to.equal('hello bold '); }); + + it('should NOT sanitize style tags', function () { + const result = sanitizeMessageContent([ + { + type: EmailBlockTypeEnum.TEXT, + content: '

Red Text

', + url: '', + }, + ]); + + expect(result[0].content).to.equal('

Red Text

'); + }); + + it('should NOT sanitize style attributes', function () { + const result = sanitizeMessageContent([ + { + type: EmailBlockTypeEnum.TEXT, + content: '

Red Text

', + url: '', + }, + ]); + + expect(result[0].content).to.equal('

Red Text

'); + }); + + it('should NOT format style attributes', function () { + const result = sanitizeMessageContent([ + { + type: EmailBlockTypeEnum.TEXT, + content: '

Red Text

', + url: '', + }, + ]); + + expect(result[0].content).to.equal('

Red Text

'); + }); }); diff --git a/apps/api/src/app/message-template/shared/sanitizer.service.ts b/apps/api/src/app/message-template/shared/sanitizer.service.ts index a28b3d4143a..ea2651d5798 100644 --- a/apps/api/src/app/message-template/shared/sanitizer.service.ts +++ b/apps/api/src/app/message-template/shared/sanitizer.service.ts @@ -1,10 +1,44 @@ import * as sanitize from 'sanitize-html'; import { IEmailBlock } from '@novu/shared'; +/** + * Options for the sanitize-html library. + * + * @see https://www.npmjs.com/package/sanitize-html#default-options + */ +const sanitizeOptions: sanitize.IOptions = { + /** + * Additional tags to allow. + */ + allowedTags: sanitize.defaults.allowedTags.concat(['style']), + allowedAttributes: { + ...sanitize.defaults.allowedAttributes, + /** + * Additional attributes to allow on all tags. + */ + '*': ['style'], + }, + /** + * Required to disable console warnings when allowing style tags. + * + * We are allowing style tags to support the use of styles in the In-App Editor. + * This is a known security risk through an XSS attack vector, + * but we are accepting this risk by dropping support for IE11. + * + * @see https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html#remote-style-sheet + */ + allowVulnerableTags: true, + /** + * Required to disable formatting of style attributes. This is useful to retain + * formatting of style attributes in the In-App Editor. + */ + parseStyleAttributes: false, +}; + export function sanitizeHTML(html: string) { if (!html) return html; - return sanitize(html); + return sanitize(html, sanitizeOptions); } export function sanitizeMessageContent(content: string | IEmailBlock[]) {