Просмотр исходного кода

fix(speaking): restrict style attr to span/td/th in report sanitiser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jimmylee 1 месяц назад
Родитель
Сommit
3270dba13e
1 измененных файлов с 13 добавлено и 3 удалено
  1. 13 3
      src/views/Student/components/SpeakingClassPanel/renderReport.ts

+ 13 - 3
src/views/Student/components/SpeakingClassPanel/renderReport.ts

@@ -1,17 +1,27 @@
 import MarkdownIt from 'markdown-it'
 import DOMPurify from 'dompurify'
 
+// html: true lets LLM-emitted raw HTML (e.g. <span style="color:…">) reach DOMPurify.
+// DOMPurify + the allowlist below are the enforcement layer, not a trust assumption.
 const md = new MarkdownIt({ html: true, breaks: false, linkify: false })
 
-// markdown-it produces table/heading/list HTML; the only raw HTML the LLM
-// emits is <span style="color:red">…</span> for highlights. Allow exactly that.
+// style is needed only for <span> colour highlights and markdown-it's
+// table-column alignment on <td>/<th>; strip it everywhere else so an
+// unexpected LLM style cannot disrupt page layout.
+const STYLE_TAGS = new Set(['span', 'td', 'th'])
+DOMPurify.addHook('afterSanitizeAttributes', (node) => {
+  if (node.hasAttribute('style') && !STYLE_TAGS.has(node.tagName.toLowerCase())) {
+    node.removeAttribute('style')
+  }
+})
+
 const ALLOWED_TAGS = [
   'h1', 'h2', 'h3', 'h4', 'h5', 'p', 'br', 'hr',
   'ul', 'ol', 'li', 'strong', 'em', 'del', 'code', 'pre',
   'blockquote', 'span',
   'table', 'thead', 'tbody', 'tr', 'th', 'td',
 ]
-const ALLOWED_ATTR = ['style', 'align']
+const ALLOWED_ATTR = ['style']
 
 /** Render class-report Markdown to sanitised HTML safe for v-html. */
 export function renderReportMarkdown(src: string): string {