mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
feat: html sanitization on all filter:parse.* hooks, closes #7872
This commit is contained in:
@@ -9,6 +9,7 @@ const nconf = require('nconf');
|
|||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
|
||||||
const user = require('../user');
|
const user = require('../user');
|
||||||
|
const posts = require('../posts');
|
||||||
|
|
||||||
const readdirAsync = util.promisify(fs.readdir);
|
const readdirAsync = util.promisify(fs.readdir);
|
||||||
|
|
||||||
@@ -124,6 +125,33 @@ Plugins.reload = async function () {
|
|||||||
console.log('');
|
console.log('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Plugins.registerHook('core', {
|
||||||
|
hook: 'filter:parse.post',
|
||||||
|
method: async (data) => {
|
||||||
|
data.postData.content = posts.sanitize(data.postData.content);
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Plugins.registerHook('core', {
|
||||||
|
hook: 'filter:parse.raw',
|
||||||
|
method: async content => posts.sanitize(content),
|
||||||
|
});
|
||||||
|
|
||||||
|
Plugins.registerHook('core', {
|
||||||
|
hook: 'filter:parse.aboutme',
|
||||||
|
method: async content => posts.sanitize(content),
|
||||||
|
});
|
||||||
|
|
||||||
|
Plugins.registerHook('core', {
|
||||||
|
hook: 'filter:parse.signature',
|
||||||
|
method: async (data) => {
|
||||||
|
data.userData.signature = posts.sanitize(data.userData.signature);
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Lower priority runs earlier
|
||||||
Object.keys(Plugins.loadedHooks).forEach(function (hook) {
|
Object.keys(Plugins.loadedHooks).forEach(function (hook) {
|
||||||
Plugins.loadedHooks[hook].sort((a, b) => a.priority - b.priority);
|
Plugins.loadedHooks[hook].sort((a, b) => a.priority - b.priority);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,12 +3,48 @@
|
|||||||
var nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
var url = require('url');
|
var url = require('url');
|
||||||
var winston = require('winston');
|
var winston = require('winston');
|
||||||
|
const sanitize = require('sanitize-html');
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var translator = require('../translator');
|
var translator = require('../translator');
|
||||||
var utils = require('../utils');
|
var utils = require('../utils');
|
||||||
|
|
||||||
|
let sanitizeConfig = {
|
||||||
|
allowedTags: sanitize.defaults.allowedTags.concat([
|
||||||
|
// Some safe-to-use tags to add
|
||||||
|
'span', 'a', 'pre', 'small',
|
||||||
|
'sup', 'sub', 'u', 'del',
|
||||||
|
'video', 'audio', 'iframe', 'embed',
|
||||||
|
'img', 'tfoot', 'h1', 'h2',
|
||||||
|
's', 'button', 'i',
|
||||||
|
]),
|
||||||
|
allowedAttributes: {
|
||||||
|
...sanitize.defaults.allowedAttributes,
|
||||||
|
a: ['href', 'hreflang', 'media', 'rel', 'target', 'type'],
|
||||||
|
img: ['alt', 'height', 'ismap', 'src', 'usemap', 'width', 'srcset'],
|
||||||
|
iframe: ['height', 'name', 'src', 'width'],
|
||||||
|
video: ['autoplay', 'controls', 'height', 'loop', 'muted', 'poster', 'preload', 'src', 'width'],
|
||||||
|
audio: ['autoplay', 'controls', 'loop', 'muted', 'preload', 'src'],
|
||||||
|
embed: ['height', 'src', 'type', 'width'],
|
||||||
|
},
|
||||||
|
globalAttributes: ['accesskey', 'class', 'contenteditable', 'dir',
|
||||||
|
'draggable', 'dropzone', 'hidden', 'id', 'lang', 'spellcheck', 'style',
|
||||||
|
'tabindex', 'title', 'translate', 'aria-expanded', 'data-*',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
process.nextTick(async () => {
|
||||||
|
// Each allowed tags should have some common global attributes...
|
||||||
|
sanitizeConfig.allowedTags.forEach((tag) => {
|
||||||
|
sanitizeConfig.allowedAttributes[tag] = _.union(sanitizeConfig.allowedAttributes[tag], sanitizeConfig.globalAttributes);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Some plugins might need to adjust or whitelist their own tags...
|
||||||
|
sanitizeConfig = await plugins.fireHook('filter:sanitize.config', sanitizeConfig);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = function (Posts) {
|
module.exports = function (Posts) {
|
||||||
Posts.urlRegex = {
|
Posts.urlRegex = {
|
||||||
regex: /href="([^"]+)"/g,
|
regex: /href="([^"]+)"/g,
|
||||||
@@ -77,6 +113,12 @@ module.exports = function (Posts) {
|
|||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Posts.sanitize = function (content) {
|
||||||
|
return sanitize(content, {
|
||||||
|
allowedTags: sanitizeConfig.allowedTags, allowedAttributes: sanitizeConfig.allowedAttributes,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function sanitizeSignature(signature) {
|
function sanitizeSignature(signature) {
|
||||||
signature = translator.escape(signature);
|
signature = translator.escape(signature);
|
||||||
var tagsToStrip = [];
|
var tagsToStrip = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user