fix(ui): sanitize markdown before chat DOM insertion
This commit is contained in:
@@ -42,6 +42,55 @@
|
||||
|
||||
let pendingAttachments = [];
|
||||
|
||||
function sanitizeHtml(html) {
|
||||
const root = document.createElement('div');
|
||||
root.innerHTML = html;
|
||||
|
||||
const blockedTags = new Set([
|
||||
'script', 'style', 'iframe', 'object', 'embed', 'link', 'meta', 'base',
|
||||
'form', 'input', 'button', 'textarea', 'select',
|
||||
]);
|
||||
|
||||
const nodes = root.querySelectorAll('*');
|
||||
for (const el of nodes) {
|
||||
const tag = el.tagName.toLowerCase();
|
||||
if (blockedTags.has(tag)) {
|
||||
el.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const attr of Array.from(el.attributes)) {
|
||||
const name = attr.name.toLowerCase();
|
||||
const value = attr.value.trim();
|
||||
if (name.startsWith('on') || name === 'style') {
|
||||
el.removeAttribute(attr.name);
|
||||
continue;
|
||||
}
|
||||
if (name === 'href' || name === 'src' || name === 'xlink:href') {
|
||||
const normalized = value.replace(/[\u0000-\u001F\u007F\s]+/g, '').toLowerCase();
|
||||
if (
|
||||
normalized.startsWith('javascript:')
|
||||
|| normalized.startsWith('vbscript:')
|
||||
|| normalized.startsWith('data:text/html')
|
||||
) {
|
||||
el.removeAttribute(attr.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tag === 'a' && el.getAttribute('target') === '_blank') {
|
||||
el.setAttribute('rel', 'noopener noreferrer');
|
||||
}
|
||||
}
|
||||
|
||||
return root.innerHTML;
|
||||
}
|
||||
|
||||
function renderSafeMarkdown(text) {
|
||||
const html = marked.parse(String(text ?? ''));
|
||||
return sanitizeHtml(html);
|
||||
}
|
||||
|
||||
function isSupportedImageMime(mimeType) {
|
||||
return mimeType === 'image/jpeg'
|
||||
|| mimeType === 'image/png'
|
||||
@@ -280,7 +329,7 @@
|
||||
// Render final response as markdown inside the assistant area
|
||||
const responseDiv = document.createElement('div');
|
||||
responseDiv.className = 'message assistant';
|
||||
responseDiv.innerHTML = marked.parse(data.content || '');
|
||||
responseDiv.innerHTML = renderSafeMarkdown(data.content || '');
|
||||
area.appendChild(responseDiv);
|
||||
}
|
||||
|
||||
@@ -326,7 +375,7 @@
|
||||
function appendAssistantMessage(content) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'message assistant';
|
||||
div.innerHTML = marked.parse(content);
|
||||
div.innerHTML = renderSafeMarkdown(content);
|
||||
messagesEl.appendChild(div);
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user