CVE-2022-1022: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site Scripting (XSS) - Stored in GitHub repository chatwoot/chatwoot prior to 2.5.0.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2022-04-21T15:15Z
Repository: https://github.com/chatwoot/chatwoot
Language: Other
Files changed: app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue, app/javascript/dashboard/components/widgets/conversation/bubble/Text.vue, app/javascript/dashboard/modules/contact/components/MergeContactSummary.vue, app/javascript/dashboard/modules/notes/components/ContactNote.vue, app/javascript/dashboard/routes/auth/Signup.vue, app/javascript/dashboard/routes/dashboard/conversation/ContactCustomAttributes.vue, app/javascript/dashboard/routes/dashboard/conversation/search/SearchMessageItem.vue, app/javascript/dashboard/routes/dashboard/settings/SettingsSubPageHeader.vue, app/javascript/dashboard/routes/dashboard/settings/agents/Index.vue, app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue, app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue, app/javascript/dashboard/routes/dashboard/settings/canned/Index.vue, app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue, app/javascript/dashboard/routes/dashboard/settings/integrationapps/MultipleIntegrationHooks.vue, app/javascript/dashboard/routes/dashboard/settings/integrations/IntegrationHelpText.vue, app/javascript/dashboard/routes/dashboard/settings/integrations/Webhook.vue, app/javascript/dashboard/routes/dashboard/settings/labels/Index.vue, app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue, app/javascript/packs/application.js, app/javascript/packs/widget.js, app/javascript/shared/components/emoji/EmojiInput.vue, app/javascript/widget/components/AgentMessageBubble.vue, app/javascript/widget/components/ChatHeader.vue, app/javascript/widget/components/ChatHeaderExpanded.vue, app/javascript/widget/components/UnreadMessage.vue, app/javascript/widget/components/UserMessageBubble.vue, package.json, yarn.lock
Commit date: 2022-04-21 11:27:28 +0530
Commit message: chore: Sanitize html content  (#4498)


Diff: diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue
index 99321eff8..ae2b83f2a 100644
--- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue
@@ -78,12 +78,12 @@
       v-tooltip="$t('CONVERSATION.FOOTER.MESSAGE_SIGN_TOOLTIP')"
       class="message-signature-wrap"
     >
       <p
         v-if="isSignatureAvailable"
+        v-dompurify-html="formatMessage(messageSignature)"
         class="message-signature"
-        v-html="formatMessage(messageSignature)"
       />
       <p v-else class="message-signature">
         {{ $t('CONVERSATION.FOOTER.MESSAGE_SIGNATURE_NOT_CONFIGURED') }}
         <router-link :to="profilePath">
           {{ $t('CONVERSATION.FOOTER.CLICK_HERE') }}
diff --git a/app/javascript/dashboard/components/widgets/conversation/bubble/Text.vue b/app/javascript/dashboard/components/widgets/conversation/bubble/Text.vue
index 1bd16d9d5..bf21d535e 100644
--- a/app/javascript/dashboard/components/widgets/conversation/bubble/Text.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/bubble/Text.vue
@@ -4,11 +4,11 @@
     :class="{
       'show--quoted': showQuotedContent,
       'hide--quoted': !showQuotedContent,
     }"
   >
-    <div class="text-content" v-html="message"></div>
+    <div v-dompurify-html="message" class="text-content"></div>
     <button
       v-if="displayQuotedButton"
       class="quoted-text--button"
       @click="toggleQuotedContent"
     >
diff --git a/app/javascript/dashboard/modules/contact/components/MergeContactSummary.vue b/app/javascript/dashboard/modules/contact/components/MergeContactSummary.vue
index 1f238e509..667359493 100644
--- a/app/javascript/dashboard/modules/contact/components/MergeContactSummary.vue
+++ b/app/javascript/dashboard/modules/contact/components/MergeContactSummary.vue
@@ -5,21 +5,21 @@
     </h5>
     <ul class="summary-items">
       <li>
         <span class="bullet">❌</span>
         <span
-          v-html="
+          v-dompurify-html="
             $t('MERGE_CONTACTS.SUMMARY.DELETE_WARNING', {
               childContactName,
             })
           "
         />
       </li>
       <li>
         <span class="bullet">✅</span>
         <span
-          v-html="
+          v-dompurify-html="
             $t('MERGE_CONTACTS.SUMMARY.ATTRIBUTE_WARNING', {
               childContactName,
               primaryContactName,
             })
           "
diff --git a/app/javascript/dashboard/modules/notes/components/ContactNote.vue b/app/javascript/dashboard/modules/notes/components/ContactNote.vue
index b781d9639..17e847a8f 100644
--- a/app/javascript/dashboard/modules/notes/components/ContactNote.vue
+++ b/app/javascript/dashboard/modules/notes/components/ContactNote.vue
@@ -33,11 +33,11 @@
         :message="$t('DELETE_NOTE.CONFIRM.MESSAGE')"
         :confirm-text="$t('DELETE_NOTE.CONFIRM.YES')"
         :reject-text="$t('DELETE_NOTE.CONFIRM.NO')"
       />
     </div>
-    <p class="note__content" v-html="formatMessage(note || '')" />
+    <p v-dompurify-html="formatMessage(note || '')" class="note__content" />
   </div>
 </template>
 
 <script>
 import Thumbnail from 'dashboard/components/widgets/Thumbnail';
diff --git a/app/javascript/dashboard/routes/auth/Signup.vue b/app/javascript/dashboard/routes/auth/Signup.vue
index 2ea4e443a..a91ab5f12 100644
--- a/app/javascript/dashboard/routes/auth/Signup.vue
+++ b/app/javascript/dashboard/routes/auth/Signup.vue
@@ -89,11 +89,11 @@
             :button-text="$t('REGISTER.SUBMIT')"
             :loading="isSignupInProgress"
             button-class="large expanded"
           >
           </woot-submit-button>
-          <p class="accept--terms" v-html="termsLink"></p>
+          <p v-dompurify-html="termsLink" class="accept--terms"></p>
         </form>
         <div class="column text-center sigin--footer">
           <span>{{ $t('REGISTER.HAVE_AN_ACCOUNT') }}</span>
           <router-link to="/app/login">
             {{
diff --git a/app/javascript/dashboard/routes/dashboard/conversation/ContactCustomAttributes.vue b/app/javascript/dashboard/routes/dashboard/conversation/ContactCustomAttributes.vue
index 6f73aa51e..a9a809385 100644
--- a/app/javascript/dashboard/routes/dashboard/conversation/ContactCustomAttributes.vue
+++ b/app/javascript/dashboard/routes/dashboard/conversation/ContactCustomAttributes.vue
@@ -7,11 +7,13 @@
     >
       <div class="custom-attribute--row__attribute">
         {{ attribute }}
       </div>
       <div>
-        <span v-html="valueWithLink(customAttributes[attribute])"></span>
+        <span
+          v-dompurify-html="valueWithLink(customAttributes[attribute])"
+        ></span>
       </div>
     </div>
     <p v-if="!listOfAttributes.length">
       {{ $t('CUSTOM_ATTRIBUTES.NOT_AVAILABLE') }}
     </p>
diff --git a/app/javascript/dashboard/routes/dashboard/conversation/search/SearchMessageItem.vue b/app/javascript/dashboard/routes/dashboard/conversation/search/SearchMessageItem.vue
index 3dd5d5cc0..9064110db 100644
--- a/app/javascript/dashboard/routes/dashboard/conversation/search/SearchMessageItem.vue
+++ b/app/javascript/dashboard/routes/dashboard/conversation/search/SearchMessageItem.vue
@@ -12,11 +12,11 @@
             />
           </div>
         </div>
         <span class="timestamp">{{ readableTime }} </span>
       </div>
-      <p class="message-content" v-html="prepareContent(content)"></p>
+      <p v-dompurify-html="prepareContent(content)" class="message-content"></p>
     </div>
   </div>
 </template>
 
 <script>
diff --git a/app/javascript/dashboard/routes/dashboard/settings/SettingsSubPageHeader.vue b/app/javascript/dashboard/routes/dashboard/settings/SettingsSubPageHeader.vue
index 283944437..ea6a6e86b 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/SettingsSubPageHeader.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/SettingsSubPageHeader.vue
@@ -1,11 +1,11 @@
 <template>
   <div class="column">
     <h2 class="page-sub-title">
       {{ headerTitle }}
     </h2>
-    <p class="small-12 column" v-html="headerContent"></p>
+    <p v-dompurify-html="headerContent" class="small-12 column"></p>
   </div>
 </template>
 
 <script>
 export default {
diff --git a/app/javascript/dashboard/routes/dashboard/settings/agents/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/agents/Index.vue
index 5714582d5..d58ca76fa 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/agents/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/agents/Index.vue
@@ -87,11 +87,11 @@
           </table>
         </div>
       </div>
       <div class="small-4 columns">
         <span
-          v-html="
+          v-dompurify-html="
             useInstallationName(
               $t('AGENT_MGMT.SIDEBAR_TXT'),
               globalConfig.installationName
             )
           "
diff --git a/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue b/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue
index 1153490a9..f89bb6eb2 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue
@@ -74,11 +74,11 @@
           </tbody>
         </table>
       </div>
     </div>
     <div class="small-4 columns">
-      <span v-html="$t('ATTRIBUTES_MGMT.SIDEBAR_TXT')"></span>
+      <span v-dompurify-html="$t('ATTRIBUTES_MGMT.SIDEBAR_TXT')"></span>
     </div>
     <woot-modal :show.sync="showEditPopup" :on-close="hideEditPopup">
       <edit-attribute
         :selected-attribute="selectedAttribute"
         :is-updating="uiFlags.isUpdating"
diff --git a/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue
index 28b8c982f..60f3c6dde 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/automation/Index.vue
@@ -79,11 +79,11 @@
           </tbody>
         </table>
       </div>
 
       <div class="small-4 columns">
-        <span v-html="$t('AUTOMATION.SIDEBAR_TXT')"></span>
+        <span v-dompurify-html="$t('AUTOMATION.SIDEBAR_TXT')"></span>
       </div>
     </div>
     <woot-modal
       :show.sync="showAddPopup"
       size="medium"
diff --git a/app/javascript/dashboard/routes/dashboard/settings/canned/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/canned/Index.vue
index 29e388e6c..bde14d385 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/canned/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/canned/Index.vue
@@ -74,11 +74,11 @@
           </tbody>
         </table>
       </div>
 
       <div class="small-4 columns">
-        <span v-html="$t('CANNED_MGMT.SIDEBAR_TXT')"></span>
+        <span v-dompurify-html="$t('CANNED_MGMT.SIDEBAR_TXT')"></span>
       </div>
     </div>
     <!-- Add Agent -->
     <woot-modal :show.sync="showAddPopup" :on-close="hideAddPopup">
       <add-canned :on-close="hideAddPopup" />
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue
index 67ccfc0ef..d5abbaaf5 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue
@@ -100,11 +100,11 @@
         </table>
       </div>
 
       <div class="small-4 columns">
         <span
-          v-html="
+          v-dompurify-html="
             useInstallationName(
               $t('INBOX_MGMT.SIDEBAR_TXT'),
               globalConfig.installationName
             )
           "
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrationapps/MultipleIntegrationHooks.vue b/app/javascript/dashboard/routes/dashboard/settings/integrationapps/MultipleIntegrationHooks.vue
index c19f52793..19ec1d597 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrationapps/MultipleIntegrationHooks.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrationapps/MultipleIntegrationHooks.vue
@@ -48,11 +48,11 @@
     <div class="small-4 columns">
       <p>
         <b>{{ integration.name }}</b>
       </p>
       <p
-        v-html="
+        v-dompurify-html="
           $t(
             `INTEGRATION_APPS.SIDEBAR_DESCRIPTION.${integration.name.toUpperCase()}`,
             { installationName: globalConfig.installationName }
           )
         "
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/IntegrationHelpText.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/IntegrationHelpText.vue
index 25049f2d0..c99f8827d 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/IntegrationHelpText.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/IntegrationHelpText.vue
@@ -2,11 +2,13 @@
   <div class="row">
     <div class="column">
       <div class="integration--description">
         <h5>{{ $t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.TITLE') }}</h5>
         <p>
-          <span v-html="$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.BODY')"></span>
+          <span
+            v-dompurify-html="$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.BODY')"
+          ></span>
         </p>
       </div>
     </div>
   </div>
 </template>
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhook.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhook.vue
index 2c489585c..e5bb621f0 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhook.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhook.vue
@@ -70,11 +70,11 @@
         </table>
       </div>
 
       <div class="small-4 columns">
         <span
-          v-html="
+          v-dompurify-html="
             useInstallationName(
               $t('INTEGRATION_SETTINGS.WEBHOOK.SIDEBAR_TXT'),
               globalConfig.installationName
             )
           "
diff --git a/app/javascript/dashboard/routes/dashboard/settings/labels/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/labels/Index.vue
index 19fde4428..66de41a00 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/labels/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/labels/Index.vue
@@ -70,11 +70,11 @@
           </tbody>
         </table>
       </div>
 
       <div class="small-4 columns">
-        <span v-html="$t('LABEL_MGMT.SIDEBAR_TXT')"></span>
+        <span v-dompurify-html="$t('LABEL_MGMT.SIDEBAR_TXT')"></span>
       </div>
     </div>
     <woot-modal :show.sync="showAddPopup" :on-close="hideAddPopup">
       <add-label @close="hideAddPopup" />
     </woot-modal>
diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue
index 5eefe008f..c9bea40f6 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue
@@ -55,11 +55,11 @@
         </table>
       </div>
 
       <div class="small-4 columns">
         <span
-          v-html="
+          v-dompurify-html="
             $t('TEAMS_SETTINGS.SIDEBAR_TXT', {
               installationName: globalConfig.installationName,
             })
           "
         />
diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js
index 0f99970c0..b0e081f98 100644
--- a/app/javascript/packs/application.js
+++ b/app/javascript/packs/application.js
@@ -36,10 +36,11 @@ import posthog from 'posthog-js';
 import {
   initializeAnalyticsEvents,
   initializeChatwootEvents,
 } from '../dashboard/helper/scriptHelpers';
 import FluentIcon from 'shared/components/FluentIcon/DashboardIcon';
+import VueDOMPurifyHTML from 'vue-dompurify-html';
 
 Vue.config.env = process.env;
 
 if (window.errorLoggingConfig) {
   Sentry.init({
@@ -52,11 +53,11 @@ if (window.errorLoggingConfig) {
 if (window.analyticsConfig) {
   posthog.init(window.analyticsConfig.token, {
     api_host: window.analyticsConfig.host,
   });
 }
-
+Vue.use(VueDOMPurifyHTML);
 Vue.use(VueRouter);
 Vue.use(VueI18n);
 Vue.use(WootUiKit);
 Vue.use(Vuelidate);
 Vue.use(VueFormulate, {
diff --git a/app/javascript/packs/widget.js b/app/javascript/packs/widget.js
index 850645581..3b9661bc7 100644
--- a/app/javascript/packs/widget.js
+++ b/app/javascript/packs/widget.js
@@ -1,17 +1,19 @@
 import Vue from 'vue';
 import Vuelidate from 'vuelidate';
 import VueI18n from 'vue-i18n';
+import VueDOMPurifyHTML from 'vue-dompurify-html';
 import VueFormulate from '@braid/vue-formulate';
 import store from '../widget/store';
 import App from '../widget/App.vue';
 import ActionCableConnector from '../widget/helpers/actionCable';
 import i18n from '../widget/i18n';
 import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
 import router from '../widget/router';
 Vue.use(VueI18n);
 Vue.use(Vuelidate);
+Vue.use(VueDOMPurifyHTML);
 
 const i18nConfig = new VueI18n({
   locale: 'en',
   messages: i18n,
 });
diff --git a/app/javascript/shared/components/emoji/EmojiInput.vue b/app/javascript/shared/components/emoji/EmojiInput.vue
index eb71ac73f..387605913 100644
--- a/app/javascript/shared/components/emoji/EmojiInput.vue
+++ b/app/javascript/shared/components/emoji/EmojiInput.vue
@@ -7,13 +7,13 @@
           :key="category"
           :class="{ active: selectedKey === category }"
           @click="changeCategory(category)"
         >
           <button
+            v-dompurify-html="emojis[category][0]"
             class="emoji--item"
             @click="changeCategory(category)"
-            v-html="emojis[category][0]"
           />
         </li>
       </ul>
     </header>
     <div class="emoji--row">
@@ -21,14 +21,14 @@
         {{ selectedKey }}
       </h5>
       <button
         v-for="emoji in emojis[selectedKey]"
         :key="emoji"
+        v-dompurify-html="emoji"
         class="emoji--item"
         track-by="$index"
         @click="onClick(emoji)"
-        v-html="emoji"
       />
     </div>
   </div>
 </template>
 
diff --git a/app/javascript/widget/components/AgentMessageBubble.vue b/app/javascript/widget/components/AgentMessageBubble.vue
index b4a304914..0695292a7 100755
--- a/app/javascript/widget/components/AgentMessageBubble.vue
+++ b/app/javascript/widget/components/AgentMessageBubble.vue
@@ -6,13 +6,13 @@
       "
       class="chat-bubble agent"
       :class="$dm('bg-white', 'dark:bg-slate-700')"
     >
       <div
+        v-dompurify-html="formatMessage(message, false)"
         class="message-content"
         :class="$dm('text-black-900', 'dark:text-slate-50')"
-        v-html="formatMessage(message, false)"
       ></div>
       <email-input
         v-if="isTemplateEmail"
         :message-id="messageId"
         :message-content-attributes="messageContentAttributes"
diff --git a/app/javascript/widget/components/ChatHeader.vue b/app/javascript/widget/components/ChatHeader.vue
index 15ffda422..906c98d14 100644
--- a/app/javascript/widget/components/ChatHeader.vue
+++ b/app/javascript/widget/components/ChatHeader.vue
@@ -20,11 +20,11 @@
       <div>
         <div
           class="font-medium text-base flex items-center"
           :class="$dm('text-black-900', 'dark:text-slate-50')"
         >
-          <span class="mr-1" v-html="title" />
+          <span v-dompurify-html="title" class="mr-1" />
           <div
             :class="
               `h-2 w-2 rounded-full leading-4
               ${isOnline ? 'bg-green-500' : 'hidden'}`
             "
diff --git a/app/javascript/widget/components/ChatHeaderExpanded.vue b/app/javascript/widget/components/ChatHeaderExpanded.vue
index fd316c3e0..c1823f504 100755
--- a/app/javascript/widget/components/ChatHeaderExpanded.vue
+++ b/app/javascript/widget/components/ChatHeaderExpanded.vue
@@ -9,18 +9,18 @@
     >
       <img v-if="avatarUrl" class="h-12 rounded-full" :src="avatarUrl" />
       <header-actions :show-popout-button="showPopoutButton" />
     </div>
     <h2
-      class=" mt-5 text-3xl mb-3 font-normal"
+      v-dompurify-html="introHeading"
+      class="mt-5 text-3xl mb-3 font-normal"
       :class="$dm('text-slate-900', 'dark:text-slate-50')"
-      v-html="introHeading"
     />
     <p
+      v-dompurify-html="introBody"
       class="text-lg leading-normal"
       :class="$dm('text-slate-700', 'dark:text-slate-200')"
-      v-html="introBody"
     />
   </header>
 </template>
 
 <script>
diff --git a/app/javascript/widget/components/UnreadMessage.vue b/app/javascript/widget/components/UnreadMessage.vue
index a3d8ee363..f7494aec4 100644
--- a/app/javascript/widget/components/UnreadMessage.vue
+++ b/app/javascript/widget/components/UnreadMessage.vue
@@ -13,11 +13,14 @@
           :status="availabilityStatus"
         />
         <span class="agent--name">{{ agentName }}</span>
         <span class="company--name"> {{ companyName }}</span>
       </div>
-      <div class="message-content" v-html="formatMessage(message, false)"></div>
+      <div
+        v-dompurify-html="formatMessage(message, false)"
+        class="message-content"
+      ></div>
     </button>
   </div>
 </template>
 
 <script>
diff --git a/app/javascript/widget/components/UserMessageBubble.vue b/app/javascript/widget/components/UserMessageBubble.vue
index 073766545..b0285b807 100755
--- a/app/javascript/widget/components/UserMessageBubble.vue
+++ b/app/javascript/widget/components/UserMessageBubble.vue
@@ -1,10 +1,10 @@
 <template>
   <div
+    v-dompurify-html="formatMessage(message, false)"
     class="chat-bubble user"
     :style="{ background: widgetColor }"
-    v-html="formatMessage(message, false)"
   />
 </template>
 
 <script>
 import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
diff --git a/package.json b/package.json
index da44aecb2..9c249cf70 100644
--- a/package.json
+++ b/package.json
@@ -60,10 +60,11 @@
     "vue": "2.6.12",
     "vue-axios": "~1.2.2",
     "vue-chartjs": "3.5.1",
     "vue-clickaway": "~2.1.0",
     "vue-color": "2.8.1",
+    "vue-dompurify-html": "^2.5.1",
     "vue-easytable": "2.5.5",
     "vue-i18n": "8.24.3",
     "vue-loader": "15.9.6",
     "vue-multiselect": "~2.1.6",
     "vue-router": "~3.5.2",
diff --git a/yarn.lock b/yarn.lock
index c32b9fc7b..959b40c3f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5841,10 +5841,15 @@ domhandler@^4.0.0, domhandler@^4.2.0:
 dompurify@2.2.7:
   version "2.2.7"
   resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.7.tgz#a5f055a2a471638680e779bd08fc334962d11fd8"
   integrity sha512-jdtDffdGNY+C76jvodNTu9jt5yYj59vuTUyx+wXdzcSwAGTYZDAQkQ7Iwx9zcGrA4ixC1syU4H3RZROqRxokxg==
 
+dompurify@^2.3.4:
+  version "2.3.6"
+  resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
+  integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==
+
 domutils@^1.5.1, domutils@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
   integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
   dependencies:
@@ -15099,10 +15104,17 @@ vue-docgen-loader@^1.5.0:
     clone "^2.1.2"
     jscodeshift "^0.7.0"
     loader-utils "^1.2.3"
     querystring "^0.2.0"
 
+vue-dompurify-html@^2.5.1:
+  version "2.5.1"
+  resolved "https://registry.npmjs.org/vue-dompurify-html/-/vue-dompurify-html-2.5.1.tgz#a754f4ac7b18eb8fe41f461cb2bb1c4956a9bd2d"
+  integrity sha512-B8rQj2jAPJJhtKHHa6jg5B3/RoKBmmUl/awP/GxWXGu75j4Y7+MHqv0DG52v0Uz0taEpHyZun34KEYMAfrPWnA==
+  dependencies:
+    dompurify "^2.3.4"
+
 vue-easytable@2.5.5:
   version "2.5.5"
   resolved "https://registry.yarnpkg.com/vue-easytable/-/vue-easytable-2.5.5.tgz#0d0ac244beb853859c76191c117311b5cf9654b5"
   integrity sha512-2dp2+OWYgCn8+g6p+7tNoCuU85OGHqk1hnQ7QnS4HUyPFVAN1n4mmG+6WkIuRKrc5wsFpsg7ZiFxHQnplos3jw==
   dependencies:

Vulnerable code:         v-html="formatMessage(messageSignature)"
    <div class="text-content" v-html="message"></div>
          v-html="
          v-html="
    <p class="note__content" v-html="formatMessage(note || '')" />
          <p class="accept--terms" v-html="termsLink"></p>
        <span v-html="valueWithLink(customAttributes[attribute])"></span>
      <p class="message-content" v-html="prepareContent(content)"></p>
    <p class="small-12 column" v-html="headerContent"></p>
          v-html="
      <span v-html="$t('ATTRIBUTES_MGMT.SIDEBAR_TXT')"></span>
        <span v-html="$t('AUTOMATION.SIDEBAR_TXT')"></span>
        <span v-html="$t('CANNED_MGMT.SIDEBAR_TXT')"></span>
          v-html="
        v-html="
          <span v-html="$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.BODY')"></span>
          v-html="
        <span v-html="$t('LABEL_MGMT.SIDEBAR_TXT')"></span>
          v-html="

            v-html="emojis[category][0]"
        v-html="emoji"
        v-html="formatMessage(message, false)"
          <span class="mr-1" v-html="title" />
      class=" mt-5 text-3xl mb-3 font-normal"
      v-html="introHeading"
      v-html="introBody"
      <div class="message-content" v-html="formatMessage(message, false)"></div>
    v-html="formatMessage(message, false)"
Fixed code:         v-dompurify-html="formatMessage(messageSignature)"
    <div v-dompurify-html="message" class="text-content"></div>
          v-dompurify-html="
          v-dompurify-html="
    <p v-dompurify-html="formatMessage(note || '')" class="note__content" />
          <p v-dompurify-html="termsLink" class="accept--terms"></p>
        <span
          v-dompurify-html="valueWithLink(customAttributes[attribute])"
        ></span>
      <p v-dompurify-html="prepareContent(content)" class="message-content"></p>
    <p v-dompurify-html="headerContent" class="small-12 column"></p>
          v-dompurify-html="
      <span v-dompurify-html="$t('ATTRIBUTES_MGMT.SIDEBAR_TXT')"></span>
        <span v-dompurify-html="$t('AUTOMATION.SIDEBAR_TXT')"></span>
        <span v-dompurify-html="$t('CANNED_MGMT.SIDEBAR_TXT')"></span>
          v-dompurify-html="
        v-dompurify-html="
          <span
            v-dompurify-html="$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.BODY')"
          ></span>
          v-dompurify-html="
        <span v-dompurify-html="$t('LABEL_MGMT.SIDEBAR_TXT')"></span>
          v-dompurify-html="
import VueDOMPurifyHTML from 'vue-dompurify-html';
Vue.use(VueDOMPurifyHTML);
import VueDOMPurifyHTML from 'vue-dompurify-html';
Vue.use(VueDOMPurifyHTML);
            v-dompurify-html="emojis[category][0]"
        v-dompurify-html="emoji"
        v-dompurify-html="formatMessage(message, false)"
          <span v-dompurify-html="title" class="mr-1" />
      v-dompurify-html="introHeading"
      class="mt-5 text-3xl mb-3 font-normal"
      v-dompurify-html="introBody"
      <div
        v-dompurify-html="formatMessage(message, false)"
        class="message-content"
      ></div>
    v-dompurify-html="formatMessage(message, false)"
    "vue-dompurify-html": "^2.5.1",
dompurify@^2.3.4:
  version "2.3.6"
  resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
  integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==

vue-dompurify-html@^2.5.1:
  version "2.5.1"
  resolved "https://registry.npmjs.org/vue-dompurify-html/-/vue-dompurify-html-2.5.1.tgz#a754f4ac7b18eb8fe41f461cb2bb1c4956a9bd2d"
  integrity sha512-B8rQj2jAPJJhtKHHa6jg5B3/RoKBmmUl/awP/GxWXGu75j4Y7+MHqv0DG52v0Uz0taEpHyZun34KEYMAfrPWnA==
  dependencies:
    dompurify "^2.3.4"