From ad3b4382152e7c3636f75a4eb487725f6e5cd06b Mon Sep 17 00:00:00 2001 From: Marcelo Santos <117441129+marcelo-m7@users.noreply.github.com> Date: Sat, 20 Sep 2025 20:55:03 +0100 Subject: [PATCH] Sanitize Supabase text rendering --- static/js/loaders.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/static/js/loaders.js b/static/js/loaders.js index f935539d..9c1b86ea 100644 --- a/static/js/loaders.js +++ b/static/js/loaders.js @@ -1,6 +1,15 @@ (function () { const messages = window.__FACODI_I18N__ || {}; + function escapeHTML(value) { + return String(value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + function resolve(path) { if (!path) { return undefined; @@ -41,21 +50,25 @@ if (window.marked && typeof window.marked.parse === 'function') { return window.marked.parse(md); } - const escaped = md - .replace(/&/g, '&') - .replace(//g, '>'); + const escaped = escapeHTML(md); return '

' + escaped.replace(/\n{2,}/g, '

').replace(/\n/g, '
') + '

'; } function toText(value, fallback = '—') { + const safeFallback = escapeHTML(fallback); if (Array.isArray(value)) { - return value.length ? value.join(', ') : fallback; + if (!value.length) { + return safeFallback; + } + return value + .map((item) => (item === null || item === undefined ? '' : escapeHTML(item))) + .filter((item) => item.length > 0) + .join(', ') || safeFallback; } if (value === null || value === undefined || value === '') { - return fallback; + return safeFallback; } - return value; + return escapeHTML(value); } function durationLabel(value) { @@ -376,7 +389,7 @@ throw topicContentError; } - const summaryHtml = topic.summary ? `

${topic.summary}

` : ''; + const summaryHtml = topic.summary ? `

${escapeHTML(topic.summary)}

` : ''; if (topicContent && topicContent.content_md) { contentEl.innerHTML = summaryHtml + renderMarkdown(topicContent.content_md); } else {