mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
ui: fix xss whitelist for katex
This commit is contained in:
1 parent
83d4f9fd5f
commit
27ab64902b
3 files changed
+38
-31
No files matched your search
@@ -1,7 +1,35 @@
|
||||
import * as Xss from 'xss';
|
||||
|
||||
const stack = [];
|
||||
let isFull = false;
|
||||
|
||||
const tagCheck = new Xss.FilterXSS({
|
||||
css: false,
|
||||
whiteList: {},
|
||||
onIgnoreTag(tag, html, options) {
|
||||
if (html.endsWith('/>')) return html;
|
||||
if (!options.isClosing) {
|
||||
stack.push(tag);
|
||||
return html;
|
||||
}
|
||||
if (stack.length === 0) {
|
||||
return html.replace(/</g, '<').replace(/>/g, '>'); // 没有标签可供闭合
|
||||
}
|
||||
if (stack[stack.length - 1] === tag) {
|
||||
stack.pop(); // 正常关闭
|
||||
return html;
|
||||
}
|
||||
if (stack.length - 2 >= 0 && stack[stack.length - 2] === tag) {
|
||||
// 可能丢失了一个结束标签
|
||||
stack.pop();
|
||||
stack.pop();
|
||||
return html;
|
||||
}
|
||||
return html.replace(/</g, '<').replace(/>/g, '>'); // 可能多出了一个结束标签
|
||||
},
|
||||
onIgnoreTagAttr(tag, name, value) {
|
||||
return value;
|
||||
},
|
||||
});
|
||||
|
||||
const xss = new Xss.FilterXSS({
|
||||
whiteList: {
|
||||
@@ -76,34 +104,13 @@ const xss = new Xss.FilterXSS({
|
||||
if (name === 'class') return value.replace(/badge/g, 'xss-badge');
|
||||
return value;
|
||||
},
|
||||
onTag(tag, html, options) {
|
||||
if (!options.isWhite || !isFull) return null;
|
||||
if (!options.isClosing) {
|
||||
stack.push(tag);
|
||||
return null;
|
||||
}
|
||||
if (stack.length === 0) return `</${tag}>`; // 没有标签可供闭合
|
||||
if (stack[stack.length - 1] === tag) {
|
||||
stack.pop(); // 正常关闭
|
||||
return null;
|
||||
}
|
||||
if (stack.length - 2 >= 0 && stack[stack.length - 2] === tag) {
|
||||
// 可能丢失了一个结束标签
|
||||
stack.pop();
|
||||
stack.pop();
|
||||
return null;
|
||||
}
|
||||
return `</${tag}>`; // 可能多出了一个结束标签
|
||||
},
|
||||
});
|
||||
|
||||
xss.process = ((original) => (html: string, full: boolean = false) => {
|
||||
function ensureTag(html: string) {
|
||||
stack.length = 0;
|
||||
isFull = full;
|
||||
const res = original(html);
|
||||
if (!full) return res;
|
||||
const res = tagCheck.process(html);
|
||||
return res + stack.map((i) => `</${i}>`).join('');
|
||||
})(xss.process.bind(xss));
|
||||
}
|
||||
|
||||
function xssProtector(md) {
|
||||
function protector(state) {
|
||||
@@ -126,4 +133,4 @@ function xssProtector(md) {
|
||||
md.core.ruler.after('linkify', 'xss', protector);
|
||||
}
|
||||
|
||||
module.exports = { xss, xssProtector };
|
||||
module.exports = { xss, ensureTag, xssProtector };
|
||||
@@ -9,7 +9,7 @@ const argv = require('cac')().parse();
|
||||
const { findFileSync } = require('@hydrooj/utils/lib/utils');
|
||||
const status = require('@hydrooj/utils/lib/status');
|
||||
const markdown = require('./markdown');
|
||||
const { xss } = require('./markdown-it-xss');
|
||||
const { xss, ensureTag } = require('./markdown-it-xss');
|
||||
|
||||
const { misc, buildContent, avatar } = global.Hydro.lib;
|
||||
|
||||
@@ -63,8 +63,8 @@ class Nunjucks extends nunjucks.Environment {
|
||||
this.addFilter('dumpYaml', (self) => yaml.dump(self));
|
||||
this.addFilter('serialize', (self, ignoreFunction = true) => serialize(self, { ignoreFunction }));
|
||||
this.addFilter('assign', (self, data) => Object.assign(self, data));
|
||||
this.addFilter('markdown', (self, html = false) => xss.process(markdown.render(self, html), true));
|
||||
this.addFilter('markdownInline', (self, html = false) => xss.process(markdown.renderInline(self, html), true));
|
||||
this.addFilter('markdown', (self, html = false) => ensureTag(markdown.render(self, html), true));
|
||||
this.addFilter('markdownInline', (self, html = false) => ensureTag(markdown.renderInline(self, html), true));
|
||||
this.addFilter('ansi', (self) => misc.ansiToHtml(self));
|
||||
this.addFilter('base64_encode', (s) => Buffer.from(s).toString('base64'));
|
||||
this.addFilter('base64_decode', (s) => Buffer.from(s, 'base64').toString());
|
||||
@@ -87,7 +87,7 @@ class Nunjucks extends nunjucks.Environment {
|
||||
else s = s[langs[0]];
|
||||
}
|
||||
if (s instanceof Array) s = buildContent(s, html ? 'html' : 'markdown', (str) => str.translate(language));
|
||||
return xss.process(html ? s : markdown.render(s), true);
|
||||
return ensureTag(html ? xss.process(s) : markdown.render(s), true);
|
||||
});
|
||||
this.addFilter('log', (self) => {
|
||||
console.log(self);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hydrooj/ui-default",
|
||||
"version": "4.31.10",
|
||||
"version": "4.31.11",
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "hydro.js",
|
||||
|
||||
Reference in new issue
Block a user