fix: escape HTML in thinking blocks to prevent XSS
All checks were successful
Build AppImage / build (push) Has been skipped
All checks were successful
Build AppImage / build (push) Has been skipped
Both bridge and frontend now properly escape &, <, > in thinking content before injecting as innerHTML. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2b2e8fe932
commit
1b1800e32b
2 changed files with 3 additions and 3 deletions
|
|
@ -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, '<').replace(/>/g, '>');
|
||||
const escaped = block.thinking.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
const collapsed = `<details class="thinking-block"><summary><svg class="thinking-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2a8 8 0 0 0-8 8c0 3.4 2.1 6.3 5 7.4V19a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1.6c2.9-1.1 5-4 5-7.4a8 8 0 0 0-8-8z"/><line x1="9" y1="22" x2="15" y2="22"/></svg><span class="thinking-label">Überlegung</span><span class="thinking-meta">${thinkLines} Zeilen</span><svg class="thinking-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg></summary><div class="thinking-content">${escaped}</div></details>\n\n`;
|
||||
fullText += collapsed;
|
||||
sendEvent('text', { text: collapsed });
|
||||
|
|
|
|||
|
|
@ -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, '<').replace(/>/g, '>');
|
||||
const answerPart = match[2].trim();
|
||||
const lines = thinkingPart.split('\n').length;
|
||||
const lines = match[1].trim().split('\n').length;
|
||||
return `<details class="thinking-block"><summary><svg class="thinking-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2a8 8 0 0 0-8 8c0 3.4 2.1 6.3 5 7.4V19a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1.6c2.9-1.1 5-4 5-7.4a8 8 0 0 0-8-8z"/><line x1="9" y1="22" x2="15" y2="22"/></svg><span class="thinking-label">Überlegung</span><span class="thinking-meta">${lines} Zeilen</span><svg class="thinking-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg></summary><div class="thinking-content">${thinkingPart}</div></details>\n\n${answerPart}`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue