CVE-2021-3649 (published 2021-07-16T14:15Z)

chatwoot is vulnerable to Inefficient Regular Expression Complexity

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: NVD-CWE-Other
cwe_name: Other
description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/chatwoot/chatwoot
commit_details: repo_url: https://github.com/chatwoot/chatwoot
author: Pranav Raj S
author_date: 2021-07-15 12:54:31+05:30
msg: fix: Use Dompurify to strip style characters (#2632)
repository: repo_url: https://github.com/chatwoot/chatwoot
repo_name: chatwoot/chatwoot
description: Open-source live-chat, email support, omni-channel desk. An alternative to Intercom, Zendesk, Salesforce Service Cloud etc. 🔥💬
repo_language: Ruby
owner: chatwoot
file_changes: filename: Message.vue
change_type: ModificationType.MODIFY
diff: @@ -91,7 +91,6 @@ import contentTypeMixin from 'shared/mixins/contentTypeMixin';
 import BubbleActions from './bubble/Actions';
 import { MESSAGE_TYPE, MESSAGE_STATUS } from 'shared/constants/messages';
 import { generateBotMessageContent } from './helpers/botMessageContentHelper';
-import { stripStyleCharacters } from './helpers/EmailContentParser';
 
 export default {
   components: {
@@ -140,7 +139,7 @@ export default {
 
       if ((replyHTMLContent || fullHTMLContent) && this.isIncoming) {
         let contentToBeParsed = replyHTMLContent || fullHTMLContent || '';
-        const parsedContent = stripStyleCharacters(contentToBeParsed);
+        const parsedContent = this.stripStyleCharacters(contentToBeParsed);
         if (parsedContent) {
           return parsedContent;
         }

programming_language: TypeScript
filename: EmailContentParser.js
change_type: ModificationType.DELETE
diff: @@ -1,12 +0,0 @@
-export const stripStyleCharacters = emailContent => {
-  let contentToBeParsed = emailContent.replace(/<style(.|\s)*?<\/style>/g, '');
-  contentToBeParsed = contentToBeParsed.replace(/style="(.*?)"/g, '');
-  let parsedContent = new DOMParser().parseFromString(
-    contentToBeParsed,
-    'text/html'
-  );
-  if (!parsedContent.getElementsByTagName('parsererror').length) {
-    return parsedContent.body.innerHTML;
-  }
-  return '';
-};

programming_language: unknown
filename: EmailContentParser.spec.js
change_type: ModificationType.DELETE
diff: @@ -1,13 +0,0 @@
-import { stripStyleCharacters } from '../EmailContentParser';
-
-describe('#stripStyleCharacters', () => {
-  it('remove style characters', () => {
-    expect(
-      stripStyleCharacters(
-        `<html><body><style type="text/css"> \n<!-- \nimg \n	{max-width:100%} \ndiv \n	{width:100%!important; \n	height:100%; \n	line-height:1.6em} \ndiv \n	{background-color:#f6f6f6} \n--> \n</style>\n<div itemscope="" itemtype="http://schema.org/EmailMessage" style="font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing:border-box; font-size:14px; width:100%!important; height:100%; line-height:1.6em; background-color:#f6f6f6; margin:0; background-color:#f6f6f6">Test Content</div>\n</body></html>`
-      )
-    ).toEqual(
-      '\n<div itemscope="" itemtype="http://schema.org/EmailMessage">Test Content</div>\n'
-    );
-  });
-});

programming_language: unknown
filename: messageFormatterMixin.js
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,5 @@
 import MessageFormatter from '../helpers/MessageFormatter';
+import DOMPurify from 'dompurify';
 
 export default {
   methods: {
@@ -17,5 +18,24 @@ export default {
 
       return `${description.slice(0, 97)}...`;
     },
+    stripStyleCharacters(message) {
+      return DOMPurify.sanitize(message, {
+        FORBID_TAGS: ['style'],
+        FORBID_ATTR: [
+          'id',
+          'class',
+          'style',
+          'bgcolor',
+          'valign',
+          'width',
+          'face',
+          'color',
+          'height',
+          'lang',
+          'align',
+          'size',
+        ],
+      });
+    },
   },
 };

programming_language: JavaScript
filename: messageFormatterMixin.spec.js
change_type: ModificationType.MODIFY
diff: @@ -14,4 +14,17 @@ describe('messageFormatterMixin', () => {
       'Chatwoot is an opensource tool. https://www.chatwoot.com'
     );
   });
+
+  it('stripStyleCharacters returns message without style tags', () => {
+    const Component = {
+      render() {},
+      mixins: [messageFormatterMixin],
+    };
+    const wrapper = shallowMount(Component);
+    const message =
+      '<b style="max-width:100%">Chatwoot is an opensource tool. https://www.chatwoot.com</b><style type="css">.message{}</style>';
+    expect(wrapper.vm.stripStyleCharacters(message)).toMatch(
+      '<b>Chatwoot is an opensource tool. https://www.chatwoot.com</b>'
+    );
+  });
 });

programming_language: TypeScript