[Security][High] Uploaded file extension is attacker-controlled → stored XSS #11
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Severity: High · Type: Security / stored XSS
Problem
In
server/src/router/v1/admin/admin.routes.js:24-27the multerfilenamekeepspath.extname(file.originalname). ThefileFilter(lines 32-35) only checksfile.mimetype, which is the client-supplied multipart Content-Type and is spoofable.So an attacker can send
Content-Type: image/png(passes the filter) withoriginalname: x.html. The file is saved as<ts>-<rand>.htmland served from/uploads/byexpress.static, which setsContent-Type: text/htmlfrom the extension. With CSP disabled (app.js:26) andcrossOriginResourcePolicy: cross-origin, that is same-origin stored HTML/JS execution.Impact
Stored XSS on the site's own origin (cookie theft / admin session hijack). Requires an authenticated uploader — but note that with the missing role checks (see the authz issue) an
editorcan upload, and even an admin account is at risk if the token leaks.Suggested fix
Derive the stored extension from the validated mimetype, never from
originalname, and ideally validate magic bytes:Also add
X-Content-Type-Options: nosniff(and considerContent-Disposition: attachmentor a restrictive CSP) when serving/uploads.