2
0

🛂 Sanitize custom CSS and head code to avoid modification of lite badge

This commit is contained in:
Baptiste Arnaud
2023-10-09 09:25:53 +02:00
parent 258de60bd2
commit 8e548248b1

View File

@ -29,6 +29,7 @@ import { injectVariablesFromExistingResult } from './variables/injectVariablesFr
import { getNextGroup } from './getNextGroup' import { getNextGroup } from './getNextGroup'
import { upsertResult } from './queries/upsertResult' import { upsertResult } from './queries/upsertResult'
import { continueBotFlow } from './continueBotFlow' import { continueBotFlow } from './continueBotFlow'
import { parseVariables } from './variables/parseVariables'
type Props = { type Props = {
version: 1 | 2 version: 1 | 2
@ -128,9 +129,9 @@ export const startSession = async ({
settings: deepParseVariables( settings: deepParseVariables(
initialState.typebotsQueue[0].typebot.variables initialState.typebotsQueue[0].typebot.variables
)(typebot.settings), )(typebot.settings),
theme: deepParseVariables( theme: sanitizeAndParseTheme(typebot.theme, {
initialState.typebotsQueue[0].typebot.variables variables: initialState.typebotsQueue[0].typebot.variables,
)(typebot.theme), }),
}, },
dynamicTheme: parseDynamicTheme(initialState), dynamicTheme: parseDynamicTheme(initialState),
messages: [], messages: [],
@ -222,9 +223,9 @@ export const startSession = async ({
settings: deepParseVariables( settings: deepParseVariables(
newSessionState.typebotsQueue[0].typebot.variables newSessionState.typebotsQueue[0].typebot.variables
)(typebot.settings), )(typebot.settings),
theme: deepParseVariables( theme: sanitizeAndParseTheme(typebot.theme, {
newSessionState.typebotsQueue[0].typebot.variables variables: initialState.typebotsQueue[0].typebot.variables,
)(typebot.theme), }),
}, },
dynamicTheme: parseDynamicTheme(newSessionState), dynamicTheme: parseDynamicTheme(newSessionState),
logs: startLogs.length > 0 ? startLogs : undefined, logs: startLogs.length > 0 ? startLogs : undefined,
@ -238,9 +239,9 @@ export const startSession = async ({
settings: deepParseVariables( settings: deepParseVariables(
newSessionState.typebotsQueue[0].typebot.variables newSessionState.typebotsQueue[0].typebot.variables
)(typebot.settings), )(typebot.settings),
theme: deepParseVariables( theme: sanitizeAndParseTheme(typebot.theme, {
newSessionState.typebotsQueue[0].typebot.variables variables: initialState.typebotsQueue[0].typebot.variables,
)(typebot.theme), }),
}, },
messages, messages,
input, input,
@ -372,7 +373,7 @@ const parseStartClientSideAction = (
const startPropsToInject = { const startPropsToInject = {
customHeadCode: isNotEmpty(typebot.settings.metadata.customHeadCode) customHeadCode: isNotEmpty(typebot.settings.metadata.customHeadCode)
? parseHeadCode(typebot.settings.metadata.customHeadCode) ? sanitizeAndParseHeadCode(typebot.settings.metadata.customHeadCode)
: undefined, : undefined,
gtmId: typebot.settings.metadata.googleTagManagerId, gtmId: typebot.settings.metadata.googleTagManagerId,
googleAnalyticsId: ( googleAnalyticsId: (
@ -398,42 +399,27 @@ const parseStartClientSideAction = (
} }
} }
const parseHeadCode = (code: string) => { const sanitizeAndParseTheme = (
code = injectTryCatch(code) theme: Theme,
{ variables }: { variables: Variable[] }
): Theme => ({
general: deepParseVariables(variables)(theme.general),
chat: deepParseVariables(variables)(theme.chat),
customCss: theme.customCss
? sanitizeAndParseHeadCode(
parseVariables(variables)(removeLiteBadgeCss(theme.customCss))
)
: undefined,
})
const sanitizeAndParseHeadCode = (code: string) => {
code = removeLiteBadgeCss(code)
return parse(code) return parse(code)
.childNodes.filter((child) => child.nodeType !== NodeType.TEXT_NODE) .childNodes.filter((child) => child.nodeType !== NodeType.TEXT_NODE)
.join('\n') .join('\n')
} }
const injectTryCatch = (headCode: string) => { const removeLiteBadgeCss = (code: string) => {
const scriptTagRegex = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi const liteBadgeCssRegex = /.*#lite-badge[\s]*{[\s\S]*}/gm
const scriptTags = headCode.match(scriptTagRegex) return code.replace(liteBadgeCssRegex, '')
if (scriptTags) {
scriptTags.forEach(function (tag) {
const wrappedTag = tag.replace(
/(<script\b[^>]*>)([\s\S]*?)(<\/script>)/gi,
function (_, openingTag, content, closingTag) {
if (!isValidJsSyntax(content)) return ''
return `${openingTag}
try {
${content}
} catch (e) {
console.warn(e);
}
${closingTag}`
}
)
headCode = headCode.replace(tag, wrappedTag)
})
}
return headCode
}
const isValidJsSyntax = (snippet: string): boolean => {
try {
new Function(snippet)
return true
} catch (err) {
return false
}
} }