From c577f56d96fa68bb0bdc1dfb14928e3a2e0213ce Mon Sep 17 00:00:00 2001 From: Ihor_Zhekov Date: Thu, 26 Feb 2026 10:53:33 +0100 Subject: [PATCH] 2 --- WebApp/app.js | 23 ++++++++++++++++++++++- WebApp/styles.css | 9 +++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/WebApp/app.js b/WebApp/app.js index 83f9d13..30b6bf4 100644 --- a/WebApp/app.js +++ b/WebApp/app.js @@ -207,13 +207,34 @@ function applyChatUI(cfg) { // ─── Chat UI helpers ────────────────────────────────────────── +/** Sanitise bot HTML: allow only , escape everything else */ +function sanitizeBotHTML(raw) { + // 1. Escape the entire string first + const esc = raw + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + // 2. Re-enable only safe tags + return esc.replace( + /<a\s+href="(https?:\/\/[^&"<>]+)"(?:\s+target="(_blank)")?>(.+?)<\/a>/gi, + (_, href, target, label) => + `${label}` + ); +} + function appendBubble(type, text, actions) { const msgs = document.getElementById('chat-messages'); if (!msgs) return; const div = document.createElement('div'); div.className = `chat-bubble chat-bubble--${type}`; div.setAttribute('role', 'article'); - div.textContent = text; // textContent only – no XSS (#6) + // Bot messages: render safe links; user/error messages: plain text only + if (type === 'bot' || type === 'error') { + div.innerHTML = sanitizeBotHTML(text); + } else { + div.textContent = text; + } if (actions?.length) { const row = document.createElement('div'); row.className = 'chat-fallback-actions'; diff --git a/WebApp/styles.css b/WebApp/styles.css index 5305ab1..52b4ae3 100644 --- a/WebApp/styles.css +++ b/WebApp/styles.css @@ -565,6 +565,15 @@ button { cursor: pointer; font-family: inherit; border: none; background: none; background: rgba(180,50,30,0.15); border: 1px solid rgba(180,50,30,0.3); color: #F5C0B0; border-bottom-left-radius: 3px; } +.chat-bubble--bot a { + color: var(--c-accent-light, #F5A623); + text-decoration: underline; + text-underline-offset: 2px; + word-break: break-word; +} +.chat-bubble--bot a:hover { + color: var(--c-accent, #D4820A); +} .chat-typing { align-self: flex-start; display: flex; gap: 4px; padding: 12px 14px; background: var(--c-surface); border: 1px solid var(--c-border);