From 1d5f23bc60463e1643fdcdff2a7978782edd472b Mon Sep 17 00:00:00 2001 From: homePC Date: Thu, 21 May 2026 14:57:19 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=89=B4=E6=9D=83?= =?UTF-8?q?=E7=BB=95=E8=BF=87=E4=BF=AE=E5=A4=8D=E4=B8=AD=E7=9A=84=E4=B8=A4?= =?UTF-8?q?=E4=B8=AA=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 路径规范化中间件只检查 API/OPEN 前缀大小写而非整个路径 避免误拦截 /api/scripts/MyScript.js 等含大写的合法请求 2. init 中间件改用 pathLower 进行比较,补全防御深度 Co-Authored-By: Claude Opus 4.7 --- back/loaders/express.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/back/loaders/express.ts b/back/loaders/express.ts index b5bf221b..e00330e9 100644 --- a/back/loaders/express.ts +++ b/back/loaders/express.ts @@ -21,18 +21,17 @@ export default ({ app }: { app: Application }) => { // Security: Path normalization middleware to prevent case variation attacks app.use((req, res, next) => { - const originalPath = req.path; - const normalizedPath = originalPath.toLowerCase(); - - // Block requests with case variations on protected paths - if (originalPath !== normalizedPath && - (normalizedPath.startsWith('/api/') || normalizedPath.startsWith('/open/'))) { + // Only check the API/OPEN prefix for case variations, not the entire path. + // This blocks /API/..., /Api/..., /OPEN/..., /Open/... bypass attempts + // while allowing legitimate mixed-case paths like /api/scripts/MyScript.js + const pathLower = req.path.toLowerCase(); + if ((pathLower.startsWith('/api/') && !req.path.startsWith('/api/')) || + (pathLower.startsWith('/open/') && !req.path.startsWith('/open/'))) { return res.status(400).json({ code: 400, - message: 'Invalid path format' + message: 'Invalid path format', }); } - next(); }); @@ -126,7 +125,7 @@ export default ({ app }: { app: Application }) => { '/api/user/notification/init', '/open/user/init', '/open/user/notification/init', - ].includes(req.path) + ].includes(pathLower) ) { return next(); }