diff --git a/app/javascript/shared/helpers/MessageFormatter.js b/app/javascript/shared/helpers/MessageFormatter.js index f57bbd1d563a..3bc89ec2f853 100644 --- a/app/javascript/shared/helpers/MessageFormatter.js +++ b/app/javascript/shared/helpers/MessageFormatter.js @@ -47,7 +47,12 @@ class MessageFormatter { const markedDownOutput = marked(withHash); return markedDownOutput; } - return marked(this.message, { breaks: true, gfm: true }); + DOMPurify.addHook('afterSanitizeAttributes', node => { + if ('target' in node) node.setAttribute('target', '_blank'); + }); + return DOMPurify.sanitize( + marked(this.message, { breaks: true, gfm: true }) + ); } get formattedMessage() { diff --git a/app/javascript/shared/helpers/specs/MessageFormatter.spec.js b/app/javascript/shared/helpers/specs/MessageFormatter.spec.js index 3ac99dbddf33..4e13fe832b42 100644 --- a/app/javascript/shared/helpers/specs/MessageFormatter.spec.js +++ b/app/javascript/shared/helpers/specs/MessageFormatter.spec.js @@ -6,14 +6,14 @@ describe('#MessageFormatter', () => { const message = 'Chatwoot is an opensource tool. [Chatwoot](https://www.chatwoot.com)'; expect(new MessageFormatter(message).formattedMessage).toMatch( - '

Chatwoot is an opensource tool. Chatwoot

' + '

Chatwoot is an opensource tool. Chatwoot

' ); }); it('should format correctly', () => { const message = 'Chatwoot is an opensource tool. https://www.chatwoot.com'; expect(new MessageFormatter(message).formattedMessage).toMatch( - '

Chatwoot is an opensource tool. https://www.chatwoot.com

' + '

Chatwoot is an opensource tool. https://www.chatwoot.com

' ); }); }); @@ -58,4 +58,14 @@ describe('#MessageFormatter', () => { ); }); }); + + describe('#sanitize', () => { + it('sanitizes markup and removes all unnecessary elements', () => { + const message = + '[xssLink](javascript:alert(document.cookie))\n[normalLink](https://google.com)**I am a bold text paragraph**'; + expect(new MessageFormatter(message).formattedMessage).toMatch( + '

xssLink
normalLinkI am a bold text paragraph

' + ); + }); + }); });