fix(Chat Trigger Node): Prevent XSS vulnerabilities and improve parameter validation (#18148)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Mutasem Aldmour
2025-08-11 12:37:07 +02:00
committed by GitHub
parent f4a04132d9
commit d4ef191be0
9 changed files with 1477 additions and 259 deletions

View File

@@ -1,6 +1,38 @@
import sanitizeHtml from 'sanitize-html';
import type { AuthenticationChatOption, LoadPreviousSessionChatOption } from './types';
function sanitizeUserInput(input: string): string {
// Sanitize HTML tags and entities
let sanitized = sanitizeHtml(input, {
allowedTags: [],
allowedAttributes: {},
});
// Remove dangerous protocols
sanitized = sanitized.replace(/javascript:/gi, '');
sanitized = sanitized.replace(/data:/gi, '');
sanitized = sanitized.replace(/vbscript:/gi, '');
return sanitized;
}
export function getSanitizedInitialMessages(initialMessages: string): string[] {
const sanitizedString = sanitizeUserInput(initialMessages);
return sanitizedString
.split('\n')
.map((line) => line.trim())
.filter((line) => line !== '');
}
export function getSanitizedI18nConfig(config: Record<string, string>): Record<string, string> {
const sanitized: Record<string, string> = {};
for (const [key, value] of Object.entries<string>(config)) {
sanitized[key] = sanitizeUserInput(value);
}
return sanitized;
}
export function createPage({
instanceId,
webhookUrl,
@@ -21,7 +53,7 @@ export function createPage({
i18n: {
en: Record<string, string>;
};
initialMessages: string[];
initialMessages: string;
mode: 'test' | 'production';
authentication: AuthenticationChatOption;
allowFileUploads?: boolean;
@@ -57,6 +89,9 @@ export function createPage({
? loadPreviousSession
: 'notSupported';
const sanitizedInitialMessages = getSanitizedInitialMessages(initialMessages);
const sanitizedI18nConfig = getSanitizedI18nConfig(en || {});
return `<!doctype html>
<html lang="en">
<head>
@@ -123,9 +158,9 @@ export function createPage({
allowFileUploads: ${sanitizedAllowFileUploads},
allowedFilesMimeTypes: '${sanitizedAllowedFilesMimeTypes}',
i18n: {
${en ? `en: ${JSON.stringify(en)},` : ''}
${Object.keys(sanitizedI18nConfig).length ? `en: ${JSON.stringify(sanitizedI18nConfig)},` : ''}
},
${initialMessages.length ? `initialMessages: ${JSON.stringify(initialMessages)},` : ''}
${sanitizedInitialMessages.length ? `initialMessages: ${JSON.stringify(sanitizedInitialMessages)},` : ''}
enableStreaming: ${!!enableStreaming},
});
})();