mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	fix: sanitize category svg image files
This commit is contained in:
		| @@ -3,6 +3,7 @@ | |||||||
| const path = require('path'); | const path = require('path'); | ||||||
| const nconf = require('nconf'); | const nconf = require('nconf'); | ||||||
| const fs = require('fs'); | const fs = require('fs'); | ||||||
|  | const sanitizeHtml = require('sanitize-html'); | ||||||
|  |  | ||||||
| const meta = require('../../meta'); | const meta = require('../../meta'); | ||||||
| const posts = require('../../posts'); | const posts = require('../../posts'); | ||||||
| @@ -121,11 +122,50 @@ uploadsController.uploadCategoryPicture = async function (req, res, next) { | |||||||
| 		return next(new Error('[[error:invalid-json]]')); | 		return next(new Error('[[error:invalid-json]]')); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (uploadedFile.path.endsWith('.svg')) { | ||||||
|  | 		await sanitizeSvg(uploadedFile.path); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	await validateUpload(uploadedFile, allowedImageTypes); | 	await validateUpload(uploadedFile, allowedImageTypes); | ||||||
| 	const filename = `category-${params.cid}${path.extname(uploadedFile.name)}`; | 	const filename = `category-${params.cid}${path.extname(uploadedFile.name)}`; | ||||||
| 	await uploadImage(filename, 'category', uploadedFile, req, res, next); | 	await uploadImage(filename, 'category', uploadedFile, req, res, next); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | async function sanitizeSvg(filePath) { | ||||||
|  | 	const dirty = await fs.promises.readFile(filePath, 'utf8'); | ||||||
|  | 	const clean = sanitizeHtml(dirty, { | ||||||
|  | 		allowedTags: [ | ||||||
|  | 			'svg', 'g', 'defs', 'linearGradient', 'radialGradient', 'stop', | ||||||
|  | 			'circle', 'ellipse', 'polygon', 'polyline', 'path', 'rect', | ||||||
|  | 			'line', 'text', 'tspan', 'use', 'symbol', 'clipPath', 'mask', 'pattern', | ||||||
|  | 			'filter', 'feGaussianBlur', 'feOffset', 'feBlend', 'feColorMatrix', 'feMerge', 'feMergeNode', | ||||||
|  | 		], | ||||||
|  | 		allowedAttributes: { | ||||||
|  | 			'*': [ | ||||||
|  | 				// Geometry | ||||||
|  | 				'x', 'y', 'x1', 'x2', 'y1', 'y2', 'cx', 'cy', 'r', 'rx', 'ry', | ||||||
|  | 				'width', 'height', 'd', 'points', 'viewBox', 'transform', | ||||||
|  |  | ||||||
|  | 				// Presentation | ||||||
|  | 				'fill', 'stroke', 'stroke-width', 'opacity', | ||||||
|  | 				'stop-color', 'stop-opacity', 'offset', 'style', 'class', | ||||||
|  |  | ||||||
|  | 				// Text | ||||||
|  | 				'text-anchor', 'font-size', 'font-family', | ||||||
|  |  | ||||||
|  | 				// Misc | ||||||
|  | 				'id', 'clip-path', 'mask', 'filter', 'gradientUnits', 'gradientTransform', | ||||||
|  | 				'xmlns', 'preserveAspectRatio', | ||||||
|  | 			], | ||||||
|  | 		}, | ||||||
|  | 		parser: { | ||||||
|  | 			lowerCaseTags: false, | ||||||
|  | 			lowerCaseAttributeNames: false, | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  | 	await fs.promises.writeFile(filePath, clean); | ||||||
|  | } | ||||||
|  |  | ||||||
| uploadsController.uploadFavicon = async function (req, res, next) { | uploadsController.uploadFavicon = async function (req, res, next) { | ||||||
| 	const uploadedFile = req.files.files[0]; | 	const uploadedFile = req.files.files[0]; | ||||||
| 	const allowedTypes = ['image/x-icon', 'image/vnd.microsoft.icon']; | 	const allowedTypes = ['image/x-icon', 'image/vnd.microsoft.icon']; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user