From afde1c5213a759b9f1eccbc885d28fe895a56799 Mon Sep 17 00:00:00 2001 From: undefined Date: Mon, 25 Mar 2024 19:28:35 +0800 Subject: [PATCH] ui: use different rule for md and mdInline (#767) --- .../ui-default/backendlib/markdown-it-xss.ts | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/packages/ui-default/backendlib/markdown-it-xss.ts b/packages/ui-default/backendlib/markdown-it-xss.ts index 079cb87ed..7602cfcf4 100644 --- a/packages/ui-default/backendlib/markdown-it-xss.ts +++ b/packages/ui-default/backendlib/markdown-it-xss.ts @@ -119,6 +119,63 @@ export const xss = new FilterXSS({ }, }); +export const xssInline = new FilterXSS({ + whiteList: { + a: ['target', 'href', 'title'], + abbr: ['title'], + address: [], + aside: [], + b: [], + bdi: ['dir'], + bdo: ['dir'], + big: [], + blockquote: ['cite', 'class'], + br: [], + caption: [], + center: [], + cite: [], + code: ['class'], + del: ['datetime'], + div: ['id', 'class'], + dl: [], + em: [], + font: ['color', 'size', 'face'], + header: [], + i: [], + ins: ['datetime'], + mark: [], + ol: [], + p: ['align', 'style'], + pre: [], + s: [], + small: [], + span: ['class', 'style'], + sub: [], + sup: [], + strong: ['id'], + tt: [], + u: [], + var: [], + }, + css: { + whiteList: { + 'font-size': true, + 'font-family': true, + 'text-indent': true, + color: true, + }, + }, + allowCommentTag: false, + stripIgnoreTag: true, + stripIgnoreTagBody: ['script'], + safeAttrValue(tag, name, value) { + if (name === 'id') return `xss-id-${value}`; + if (name === 'class') return value.replace(/badge/g, 'xss-badge'); + if (name === 'href') return value.trim().startsWith('javascript:') ? '#' : value; + return value; + }, +}); + export function ensureTag(html: string) { stack.length = 0; const res = tagCheck.process(html); @@ -127,16 +184,17 @@ export function ensureTag(html: string) { export function xssProtector(md) { function protector(state) { + const processor = state.inlineMode ? xssInline : xss; for (let i = 0; i < state.tokens.length; i++) { const cur = state.tokens[i]; if (cur.type === 'html_block') { - cur.content = xss.process(cur.content); + cur.content = processor.process(cur.content); } if (cur.type === 'inline') { const inlineTokens = cur.children; for (let ii = 0; ii < inlineTokens.length; ii++) { if (inlineTokens[ii].type === 'html_inline') { - inlineTokens[ii].content = xss.process(inlineTokens[ii].content); + inlineTokens[ii].content = processor.process(inlineTokens[ii].content); } } }