From 4a494739ae308294fc8181af325fe3b57da825a7 Mon Sep 17 00:00:00 2001 From: yemur <2085151308@qq.com> Date: Fri, 27 Feb 2026 10:27:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=A5=E9=87=8D=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E7=BB=95=E8=BF=87=E6=BC=8F=E6=B4=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ back/loaders/express.ts | 16 ++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 709791ed..93241930 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ __pycache__ /shell/preload/notify.* /shell/preload/*-notify.json /shell/preload/__ql_notify__.* +docs/ +docs/* diff --git a/back/loaders/express.ts b/back/loaders/express.ts index 63065a21..67ea9bcf 100644 --- a/back/loaders/express.ts +++ b/back/loaders/express.ts @@ -36,7 +36,8 @@ export default ({ app }: { app: Application }) => { secret: config.jwt.secret, algorithms: ['HS384'], }).unless({ - path: [...config.apiWhiteList, /^\/(?!api\/).*/], + // Use case-insensitive regex to prevent bypassing JWT via uppercase paths like /Api/ + path: [...config.apiWhiteList, /^\/(?!api\/)/i], }), ); @@ -51,22 +52,25 @@ export default ({ app }: { app: Application }) => { }); app.use(async (req: Request, res, next) => { - if (!['/open/', '/api/'].some((x) => req.path.startsWith(x))) { + // Normalize path to lowercase to prevent case-sensitivity bypass (e.g. /Open/, /API/) + const normalizedPath = req.path.toLowerCase(); + if (!['/open/', '/api/'].some((x) => normalizedPath.startsWith(x))) { return next(); } const headerToken = getToken(req); - if (req.path.startsWith('/open/')) { + if (normalizedPath.startsWith('/open/')) { const apps = await shareStore.getApps(); const doc = apps?.filter((x) => x.tokens?.find((y) => y.value === headerToken), )?.[0]; if (doc && doc.tokens && doc.tokens.length > 0) { const currentToken = doc.tokens.find((x) => x.value === headerToken); - const keyMatch = req.path.match(/\/open\/([a-z]+)\/*/); - const key = keyMatch && keyMatch[1]; + // Use case-insensitive match and normalize key to prevent scope bypass via uppercase paths + const keyMatch = req.path.match(/\/open\/([a-zA-Z]+)\/*/); + const key = keyMatch && keyMatch[1]?.toLowerCase(); if ( - doc.scopes.includes(key as any) && + key && doc.scopes.includes(key as any) && currentToken && currentToken.expiration >= Math.round(Date.now() / 1000) ) {