Multer fileFilter校验扩展名报错时不合规文件仍被保存问题
Multer文件过滤后非法文件仍被存储问题修复
预期功能
配置Express的Multer中间件,仅允许保存扩展名为pdf的上传文件,非pdf格式文件返回错误提示且不予存储。
问题现象
上传jpg等非pdf格式文件时,接口可正确返回预期的please upload PDF file extension错误响应,但不符合格式要求的文件依然被存入指定的images目录,与预期逻辑不符。
问题复现代码
const express = require("express"); const app = new express(); const multer = require("multer"); const upload = multer({ dest: "images", // 文件存储目录 limits: 100000, // 原代码此处写法有误,限制文件大小需传入对象指定fileSize字段 fileFilter(req, file, cb) { if (!file.originalname.endsWith("pdf")) { cb(new Error("please upload PDF file extension")); // 此处缺少return终止逻辑,后续代码仍会执行 } cb(undefined, true); }, }); app.post("/upload", upload.single("upload"), (req, res) => { res.send(); }); app.listen(8000, () => { console.log("server fired off"); });
故障原因
fileFilter方法存在执行流漏洞:判断到非pdf文件触发错误回调后,没有终止函数执行,后续的cb(undefined, true)会照常运行,相当于同时向Multer传递了「文件非法」和「文件允许通过」两个矛盾指令,最终导致错误正常返回,但文件依然被写入存储目录。
另外原代码的limits配置写法错误,直接传入数字不会生效,需要传入对象通过fileSize字段指定大小限制;原后缀判断逻辑也存在漏洞,endsWith("pdf")会把xxxpdf这类无后缀的文件误判为合法pdf,且不支持大写.PDF后缀校验。
修复后代码
const express = require("express"); const app = new express(); const multer = require("multer"); const upload = multer({ dest: "images", limits: { fileSize: 100000 // 正确配置1MB大小限制 }, fileFilter(req, file, cb) { // 用正则匹配.pdf后缀,兼容大写格式,同时校验后缀前的点避免误判无后缀文件 if (!/\.pdf$/i.test(file.originalname)) { // 错误回调后加return,阻断后续逻辑执行 return cb(new Error("please upload PDF file extension")); } cb(undefined, true); }, }); // 增加专属错误处理中间件,统一捕获上传阶段的错误 app.post("/upload", upload.single("upload"), (req, res) => { res.send(); }, (error, req, res, next) => { res.status(400).send({ error: error.message }); }); app.listen(8000, () => { console.log("server fired off"); });
内容的提问来源于stack exchange,提问作者mahir
相关产品推荐
相关产品推荐

