You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wiki/server/modules/rendering/html-security/renderer.js

106 lines
3.7 KiB

const { JSDOM } = require('jsdom')
const createDOMPurify = require('dompurify')
module.exports = {
async init(input, config) {
if (config.safeHTML) {
const window = new JSDOM('').window
const DOMPurify = createDOMPurify(window)
const allowedAttrs = ['v-pre', 'v-slot:tabs', 'v-slot:content', 'target']
const allowedTags = ['tabset', 'template']
if (config.allowDrawIoUnsafe) {
allowedTags.push('foreignObject')
DOMPurify.addHook('uponSanitizeElement', (elm) => {
if (elm.querySelectorAll) {
const breaks = elm.querySelectorAll('foreignObject br, foreignObject p')
if (breaks && breaks.length) {
for (let i = 0; i < breaks.length; i++) {
breaks[i].parentNode.replaceChild(
window.document.createElement('div'),
breaks[i]
)
}
}
}
})
}
if (config.allowIFrames) {
allowedTags.push('iframe')
allowedAttrs.push('allow')
}
//Changes to keep interactive plantuml object tag
//only allow specific attributes for plantuml object node
if (typeof pumlImageFormat !== 'undefined' &&
pumlImageFormat &&
pumlImageFormat == 'svg') {
allowedTags.push('object')
allowedAttrs.push('data')
allowedAttrs.push('type')
allowedAttrs.push('style')
allowedAttrs.push('class')
allowedAttrs.push('alt')
}
DOMPurify.addHook('uponSanitizeElement', (node, data) => {
// keep object node only if it is
// authorised plantuml using the configured plantuml server
// force attribute values to configured params
// insert the plantuml inside the object as text for search
let isPumlNode=false
if (data.tagName === 'object' &&
typeof pumlServer !== 'undefined' && pumlServer &&
typeof pumlObjectStyle !== 'undefined' && pumlObjectStyle &&
typeof pumlObjectType !== 'undefined' && pumlObjectType &&
typeof pumlObjectClass !== 'undefined' && pumlObjectClass
) {
//console.log ("Found object node - validating")
//remove node if it doesn't conform to plantuml structure
if (!( 'data' in node.attributes
&& 'class' in node.attributes
&& 'style' in node.attributes
&& 'type' in node.attributes
&& 'alt' in node.attributes)
) {
//console.log ("Attribute mismatch - removing object node")
return node.parentNode.removeChild(node)
}
dataAttribute = node.getAttribute ('data')
//only allow configured plantuml server and image format in url
if (dataAttribute
&& dataAttribute.startsWith(`${pumlServer}/${pumlImageFormat}`)
) {
//console.log ("Plantuml node found - setting atribute values")
isPumlNode=true
node.setAttribute ('type', pumlObjectType)
node.setAttribute ('style', pumlObjectStyle)
node.setAttribute ('class', pumlObjectClass)
node.setAttribute ('alt', '')
}
//if not a plantuml node, then sanitise it
if (!isPumlNode) {
console.log ("Removing unknown object node")
return node.parentNode.removeChild(node)
}
}
})
//End changes to keep interactive plantuml object tag
input = DOMPurify.sanitize(input, {
ADD_ATTR: allowedAttrs,
ADD_TAGS: allowedTags,
HTML_INTEGRATION_POINTS: { foreignobject: true }
})
}
return input
}
}