From 278cd7173ddac3360906b33356768f254e8892ef Mon Sep 17 00:00:00 2001 From: NGPixel Date: Wed, 11 Dec 2019 23:35:54 -0500 Subject: [PATCH] feat: rendering security module --- package.json | 1 + server/graph/resolvers/rendering.js | 16 ++++---- .../html-codehighlighter/definition.yml | 1 + .../modules/rendering/html-core/renderer.js | 19 +++++++++- .../rendering/html-mathjax/definition.yml | 1 + .../rendering/html-security/definition.yml | 14 +++---- .../rendering/html-security/renderer.js | 37 ++++++++++++++++++- yarn.lock | 13 +++++++ 8 files changed, 82 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index cbab3706..6658e81f 100644 --- a/package.json +++ b/package.json @@ -161,6 +161,7 @@ "uuid": "3.3.3", "validate.js": "0.13.1", "winston": "3.2.1", + "xss": "1.0.6", "yargs": "15.0.2" }, "devDependencies": { diff --git a/server/graph/resolvers/rendering.js b/server/graph/resolvers/rendering.js index 0a794432..4df266b1 100644 --- a/server/graph/resolvers/rendering.js +++ b/server/graph/resolvers/rendering.js @@ -19,14 +19,16 @@ module.exports = { ...rendererInfo, ...rdr, config: _.sortBy(_.transform(rdr.config, (res, value, key) => { - const configData = _.get(rendererInfo.props, key, {}) - res.push({ - key, - value: JSON.stringify({ - ...configData, - value + const configData = _.get(rendererInfo.props, key, false) + if (configData) { + res.push({ + key, + value: JSON.stringify({ + ...configData, + value + }) }) - }) + } }, []), 'key') } }) diff --git a/server/modules/rendering/html-codehighlighter/definition.yml b/server/modules/rendering/html-codehighlighter/definition.yml index 7d0b2d21..656931ff 100644 --- a/server/modules/rendering/html-codehighlighter/definition.yml +++ b/server/modules/rendering/html-codehighlighter/definition.yml @@ -5,4 +5,5 @@ author: requarks.io icon: mdi-code-braces enabledDefault: true dependsOn: htmlCore +step: pre props: {} diff --git a/server/modules/rendering/html-core/renderer.js b/server/modules/rendering/html-core/renderer.js index 8fc079eb..28412461 100644 --- a/server/modules/rendering/html-core/renderer.js +++ b/server/modules/rendering/html-core/renderer.js @@ -14,7 +14,11 @@ module.exports = { return '' } - for (let child of this.children) { + // -------------------------------- + // STEP: PRE + // -------------------------------- + + for (let child of _.reject(this.children, ['step', 'post'])) { const renderer = require(`../${_.kebabCase(child.key)}/renderer.js`) renderer.init($, child.config) } @@ -211,6 +215,17 @@ module.exports = { headers.push(headerSlug) }) - return $.html('body').replace('', '').replace('', '') + let output = $.html('body').replace('', '').replace('', '') + + // -------------------------------- + // STEP: POST + // -------------------------------- + + for (let child of _.filter(this.children, ['step', 'post'])) { + const renderer = require(`../${_.kebabCase(child.key)}/renderer.js`) + output = renderer.init(output, child.config) + } + + return output } } diff --git a/server/modules/rendering/html-mathjax/definition.yml b/server/modules/rendering/html-mathjax/definition.yml index cbe96f29..9584c26c 100644 --- a/server/modules/rendering/html-mathjax/definition.yml +++ b/server/modules/rendering/html-mathjax/definition.yml @@ -5,4 +5,5 @@ author: requarks.io icon: mdi-function-variant enabledDefault: false dependsOn: htmlCore +step: pre props: {} diff --git a/server/modules/rendering/html-security/definition.yml b/server/modules/rendering/html-security/definition.yml index 14af5b23..38f043cb 100644 --- a/server/modules/rendering/html-security/definition.yml +++ b/server/modules/rendering/html-security/definition.yml @@ -5,14 +5,10 @@ author: requarks.io icon: mdi-fire enabledDefault: true dependsOn: htmlCore +step: post props: - stripJS: + safeHTML: type: Boolean - title: Strip Javascript - default: false - hint: Javascript code within code blocks won't be affected - filterBadWords: - type: Boolean - title: Filter Bad Words - default: false - hint: Replace bad words with asterisks + title: Sanitize HTML + default: true + hint: Sanitize HTML from unsafe attributes and tags that could lead to XSS attacks diff --git a/server/modules/rendering/html-security/renderer.js b/server/modules/rendering/html-security/renderer.js index 67c19c89..1fac3975 100644 --- a/server/modules/rendering/html-security/renderer.js +++ b/server/modules/rendering/html-security/renderer.js @@ -1,5 +1,38 @@ -module.exports = { - init($, config) { +const xss = require('xss') +module.exports = { + async init(input, config) { + if (config.safeHTML) { + input = xss(input, { + whiteList: { + ...xss.whiteList, + a: ['class', 'id', 'href', 'target', 'title'], + blockquote: ['class', 'id'], + code: ['class'], + div: ['class', 'id'], + em: ['class'], + h1: ['class', 'id'], + h2: ['class', 'id'], + h3: ['class', 'id'], + h4: ['class', 'id'], + h5: ['class', 'id'], + h6: ['class', 'id'], + img: ['alt', 'class', 'draggable', 'height', 'src', 'width'], + li: ['class'], + ol: ['class'], + p: ['class'], + pre: ['class'], + strong: ['class'], + table: ['border', 'class', 'id', 'width'], + tbody: ['class'], + td: ['align', 'class', 'colspan', 'rowspan', 'valign'], + th: ['align', 'class', 'colspan', 'rowspan', 'valign'], + thead: ['class'], + tr: ['class', 'rowspan', 'align', 'valign'], + ul: ['class'] + } + }) + } + return input } } diff --git a/yarn.lock b/yarn.lock index 42fceaed..8edf9e66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4447,6 +4447,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssfilter@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" + integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= + cssnano-preset-default@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" @@ -14363,6 +14368,14 @@ xpath@0.0.27: resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92" integrity sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ== +xss@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.6.tgz#eaf11e9fc476e3ae289944a1009efddd8a124b51" + integrity sha512-6Q9TPBeNyoTRxgZFk5Ggaepk/4vUOYdOsIUYvLehcsIZTFjaavbVnsuAkLA5lIFuug5hw8zxcB9tm01gsjph2A== + dependencies: + commander "^2.9.0" + cssfilter "0.0.10" + xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"