🛂 Sanitize custom CSS and head code to avoid modification of lite badge
This commit is contained in:
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user