2
This commit is contained in:
@@ -207,13 +207,34 @@ function applyChatUI(cfg) {
|
||||
|
||||
// ─── Chat UI helpers ──────────────────────────────────────────
|
||||
|
||||
/** Sanitise bot HTML: allow only <a href="..." target="...">…</a>, escape everything else */
|
||||
function sanitizeBotHTML(raw) {
|
||||
// 1. Escape the entire string first
|
||||
const esc = raw
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
// 2. Re-enable only safe <a> tags
|
||||
return esc.replace(
|
||||
/<a\s+href="(https?:\/\/[^&"<>]+)"(?:\s+target="(_blank)")?>(.+?)<\/a>/gi,
|
||||
(_, href, target, label) =>
|
||||
`<a href="${href}" target="${target || '_blank'}" rel="noopener noreferrer">${label}</a>`
|
||||
);
|
||||
}
|
||||
|
||||
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 <a> 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';
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user