From 6e60e3b9469474edb9cb71bcd676dafbb1f623d6 Mon Sep 17 00:00:00 2001 From: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:18:35 +0530 Subject: [PATCH] fix: use safe DOM manipulation for article heading permalinks Fixes [CW-6300](https://linear.app/chatwoot/issue/CW-6300/advisory-stored-dom-xss-in-chatwoot-help-center-article-heading) --- app/javascript/portal/portalHelpers.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/javascript/portal/portalHelpers.js b/app/javascript/portal/portalHelpers.js index 1fdc51276..f183a89fc 100644 --- a/app/javascript/portal/portalHelpers.js +++ b/app/javascript/portal/portalHelpers.js @@ -14,10 +14,19 @@ export const getHeadingsfromTheArticle = () => { const rows = []; const articleElement = document.getElementById('cw-article-content'); articleElement.querySelectorAll('h1, h2, h3').forEach(element => { - const slug = slugifyWithCounter(element.innerText); + const headingText = element.innerText; + const slug = slugifyWithCounter(headingText); element.id = slug; element.className = 'scroll-mt-24 heading'; - element.innerHTML += ``; + + const permalink = document.createElement('a'); + permalink.className = 'permalink text-slate-600 ml-3'; + permalink.href = `#${slug}`; + permalink.title = headingText; + permalink.dataset.turbolinks = 'false'; + permalink.textContent = '#'; + element.appendChild(permalink); + rows.push({ slug, title: element.innerText,