From 1b1800e32b4cdf2357c445dd73e57690a8242058 Mon Sep 17 00:00:00 2001 From: Eddy Date: Mon, 20 Apr 2026 22:41:42 +0200 Subject: [PATCH] fix: escape HTML in thinking blocks to prevent XSS Both bridge and frontend now properly escape &, <, > in thinking content before injecting as innerHTML. Co-Authored-By: Claude Opus 4.6 --- scripts/claude-bridge.js | 2 +- src/lib/components/ChatPanel.svelte | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/claude-bridge.js b/scripts/claude-bridge.js index dd2a006..0626d07 100644 --- a/scripts/claude-bridge.js +++ b/scripts/claude-bridge.js @@ -545,7 +545,7 @@ async function sendMessage(message, requestId, model = null, contextOverride = n } else if (block.type === 'thinking' && block.thinking) { // Extended Thinking — als kollabierbaren Block im ChatGPT/Claude.ai-Style const thinkLines = block.thinking.split('\n').length; - const escaped = block.thinking.replace(//g, '>'); + const escaped = block.thinking.replace(/&/g, '&').replace(//g, '>'); const collapsed = `
Überlegung${thinkLines} Zeilen
${escaped}
\n\n`; fullText += collapsed; sendEvent('text', { text: collapsed }); diff --git a/src/lib/components/ChatPanel.svelte b/src/lib/components/ChatPanel.svelte index b950897..6a41d0f 100644 --- a/src/lib/components/ChatPanel.svelte +++ b/src/lib/components/ChatPanel.svelte @@ -68,9 +68,9 @@ for (const pattern of thinkingPatterns) { const match = text.match(pattern); if (match && match[1] && match[1].split('\n').length > 5) { - const thinkingPart = match[1].trim(); + const thinkingPart = match[1].trim().replace(/&/g, '&').replace(//g, '>'); const answerPart = match[2].trim(); - const lines = thinkingPart.split('\n').length; + const lines = match[1].trim().split('\n').length; return `
Überlegung${lines} Zeilen
${thinkingPart}
\n\n${answerPart}`; } }