diff --git a/app/javascript/sdk/IFrameHelper.js b/app/javascript/sdk/IFrameHelper.js index 3ab1ba1f5..25f90912d 100644 --- a/app/javascript/sdk/IFrameHelper.js +++ b/app/javascript/sdk/IFrameHelper.js @@ -50,11 +50,35 @@ const updateCampaignReadStatus = baseDomain => { }); }; +const sanitizeURL = url => { + if (url === '') return ''; + + try { + // any invalid url will not be accepted + // example - JaVaScRiP%0at:alert(document.domain)" + // this has an obfuscated javascript protocol + const parsedURL = new URL(url); + + // filter out dangerous protocols like `javascript`, `data`, `vbscript` + if (!['https', 'http'].includes(parsedURL.protocol)) { + throw new Error('Invalid Protocol'); + } + } catch (e) { + // eslint-disable-next-line no-console + console.error('Invalid URL', e); + } + + return 'about:blank'; // blank page URL +}; + export const IFrameHelper = { getUrl({ baseUrl, websiteToken }) { + baseUrl = sanitizeURL(baseUrl); return `${baseUrl}/widget?website_token=${websiteToken}`; }, createFrame: ({ baseUrl, websiteToken }) => { + baseUrl = sanitizeURL(baseUrl); + if (IFrameHelper.getAppFrame()) { return; } @@ -102,10 +126,12 @@ export const IFrameHelper = { window.onmessage = e => { if ( typeof e.data !== 'string' || - e.data.indexOf('chatwoot-widget:') !== 0 + e.data.indexOf('chatwoot-widget:') !== 0 || + e.origin !== window.location.origin ) { return; } + const message = JSON.parse(e.data.replace('chatwoot-widget:', '')); if (typeof IFrameHelper.events[message.event] === 'function') { IFrameHelper.events[message.event](message); @@ -140,7 +166,9 @@ export const IFrameHelper = { }, setupAudioListeners: () => { - const { baseUrl = '' } = window.$chatwoot; + let { baseUrl = '' } = window.$chatwoot; + baseUrl = sanitizeURL(baseUrl); + getAlertAudio(baseUrl, { type: 'widget', alertTone: 'ding' }).then(() => initOnEvents.forEach(event => { document.removeEventListener( @@ -234,6 +262,7 @@ export const IFrameHelper = { }, popoutChatWindow: ({ baseUrl, websiteToken, locale }) => { + baseUrl = sanitizeURL(baseUrl); const cwCookie = Cookies.get('cw_conversation'); window.$chatwoot.toggle('close'); popoutChatWindow(baseUrl, websiteToken, locale, cwCookie);