From 5ae8d553ed1ba276b92afeb2b32b26623209d225 Mon Sep 17 00:00:00 2001 From: Shlomo <78599753+ShlomoCode@users.noreply.github.com> Date: Mon, 15 Dec 2025 20:16:38 +0200 Subject: [PATCH] fix: disallow inline viewing of unsafe files (#13833) --- src/middleware/index.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/middleware/index.js b/src/middleware/index.js index 14cb3138e1..02024b8a19 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -273,10 +273,19 @@ middleware.buildSkinAsset = helpers.try(async (req, res, next) => { middleware.addUploadHeaders = function addUploadHeaders(req, res, next) { // Trim uploaded files' timestamps when downloading + force download if html let basename = path.basename(req.path); - const extname = path.extname(req.path); - if (req.path.startsWith('/uploads/files/') && middleware.regexes.timestampedUpload.test(basename)) { - basename = basename.slice(14); - res.header('Content-Disposition', `${extname.startsWith('.htm') ? 'attachment' : 'inline'}; filename="${basename}"`); + const extname = path.extname(req.path).toLowerCase(); + const unsafeExtensions = [ + '.html', '.htm', '.xhtml', '.mht', '.mhtml', '.stm', '.shtm', '.shtml', + '.svg', '.svgz', + '.xml', '.xsl', '.xslt', + ]; + const isInlineSafe = !unsafeExtensions.includes(extname); + const dispositionType = isInlineSafe ? 'inline' : 'attachment'; + if (req.path.startsWith('/uploads/files/')) { + if (middleware.regexes.timestampedUpload.test(basename)) { + basename = basename.slice(14); + } + res.header('Content-Disposition', `${dispositionType}; filename="${basename}"`); } next();