Commit 98bf0d9c authored by NGPixel's avatar NGPixel

fix: escape mustache template chars in content

parent 2ff0e42c
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
"js-base64": "2.5.2", "js-base64": "2.5.2",
"js-binary": "1.2.0", "js-binary": "1.2.0",
"js-yaml": "3.13.1", "js-yaml": "3.13.1",
"jsdom": "16.2.2",
"jsonwebtoken": "8.5.1", "jsonwebtoken": "8.5.1",
"katex": "0.11.1", "katex": "0.11.1",
"klaw": "3.0.0", "klaw": "3.0.0",
......
...@@ -230,12 +230,31 @@ module.exports = { ...@@ -230,12 +230,31 @@ module.exports = {
headers.push(headerSlug) headers.push(headerSlug)
}) })
let output = decodeEscape($.html('body').replace('<body>', '').replace('</body>', '')) // --------------------------------
// Escape mustache expresions
// --------------------------------
function iterateMustacheNode (node) {
const list = $(node).contents().toArray()
list.forEach(item => {
if (item.type === 'text') {
const rawText = $(item).text()
if (rawText.indexOf('{{') >= 0 && rawText.indexOf('}}') > 1) {
$(item).parent().attr('v-pre', true)
}
} else {
iterateMustacheNode(item)
}
})
}
iterateMustacheNode($.root())
// -------------------------------- // --------------------------------
// STEP: POST // STEP: POST
// -------------------------------- // --------------------------------
let output = decodeEscape($.html('body').replace('<body>', '').replace('</body>', ''))
for (let child of _.sortBy(_.filter(this.children, ['step', 'post']), ['order'])) { for (let child of _.sortBy(_.filter(this.children, ['step', 'post']), ['order'])) {
const renderer = require(`../${_.kebabCase(child.key)}/renderer.js`) const renderer = require(`../${_.kebabCase(child.key)}/renderer.js`)
output = await renderer.init(output, child.config) output = await renderer.init(output, child.config)
......
...@@ -13,3 +13,10 @@ props: ...@@ -13,3 +13,10 @@ props:
title: Sanitize HTML title: Sanitize HTML
default: true default: true
hint: Sanitize HTML from unsafe attributes and tags that could lead to XSS attacks hint: Sanitize HTML from unsafe attributes and tags that could lead to XSS attacks
order: 1
allowIFrames:
type: Boolean
title: Allow iframes
default: false
hint: iframes will not be stripped if enabled. (Not recommended)
order: 2
const xss = require('xss') const { JSDOM } = require('jsdom')
const createDOMPurify = require('dompurify')
module.exports = { module.exports = {
async init(input, config) { async init(input, config) {
if (config.safeHTML) { if (config.safeHTML) {
input = xss(input, { const window = new JSDOM('').window
whiteList: { const DOMPurify = createDOMPurify(window)
...xss.whiteList,
a: ['class', 'id', 'href', 'style', 'target', 'title', 'rel'], const allowedAttrs = ['v-pre', 'v-slot:tabs', 'v-slot:content']
blockquote: ['class', 'id', 'style'], const allowedTags = ['tabset', 'template']
code: ['class', 'style'],
details: ['class', 'style'], if (config.allowIFrames) {
defs: ['stroke', 'fill', 'stroke-width', 'transform', 'id'], allowedTags.push('iframe')
div: ['class', 'id', 'style'], }
em: ['class', 'style'],
figcaption: ['class', 'style', 'id'], input = DOMPurify.sanitize(input, {
figure: ['class', 'style', 'id'], ADD_ATTR: allowedAttrs,
g: ['transform', 'stroke', 'stroke-width', 'fill'], ADD_TAGS: allowedTags
h1: ['class', 'id', 'style'],
h2: ['class', 'id', 'style'],
h3: ['class', 'id', 'style'],
h4: ['class', 'id', 'style'],
h5: ['class', 'id', 'style'],
h6: ['class', 'id', 'style'],
i: ['class', 'id', 'style'],
img: ['alt', 'class', 'draggable', 'height', 'id', 'src', 'style', 'width'],
input: ['class', 'disabled', 'type', 'checked', 'id'],
kbd: ['class'],
label: ['class', 'id', 'for'],
li: ['class', 'id', 'style'],
mark: ['class', 'style'],
ol: ['class', 'id', 'style', 'start'],
p: ['class', 'id', 'style'],
path: ['d', 'style', 'id'],
pre: ['class', 'id', 'style'],
section: ['class', 'style'],
span: ['class', 'style', 'aria-hidden'],
strong: ['class', 'style'],
summary: ['class', 'id', 'style'],
svg: ['width', 'height', 'viewbox', 'preserveaspectratio', 'style'],
table: ['border', 'class', 'id', 'style', 'width'],
tabset: [],
tbody: ['class', 'style'],
td: ['align', 'class', 'colspan', 'rowspan', 'style', 'valign', 'id'],
template: ['v-slot:tabs', 'v-slot:content'],
th: ['align', 'class', 'colspan', 'rowspan', 'style', 'valign', 'id'],
thead: ['class', 'style'],
tr: ['class', 'rowspan', 'style', 'align', 'valign', 'id'],
ul: ['class', 'id', 'style'],
use: ['href', 'transform']
},
css: false
}) })
} }
return input return input
......
This diff was suppressed by a .gitattributes entry.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment