From 099b91a2a29d142ddb4b0c62d8bfd9bb027fae3c Mon Sep 17 00:00:00 2001 From: Mohit Malhotra Date: Fri, 13 Feb 2026 19:52:29 +0530 Subject: [PATCH] fix: prevent `use` with multi-slash path from matching all routes Paths consisting entirely of slashes (e.g. `//`) were reduced to an empty string by `loosen()`, causing `router.use('//', handler)` to incorrectly match every request. Preserve the original path when trailing slash removal would produce an empty string. Fixes expressjs/express#4557 Signed-off-by: Mohit Malhotra --- lib/layer.js | 14 ++++++++--- test/router.js | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/lib/layer.js b/lib/layer.js index 6a4408f..8d14cab 100644 --- a/lib/layer.js +++ b/lib/layer.js @@ -241,7 +241,15 @@ function loosen (path) { return path } - return Array.isArray(path) - ? path.map(function (p) { return loosen(p) }) - : String(path).replace(TRAILING_SLASH_REGEXP, '') + if (Array.isArray(path)) { + return path.map(function (p) { return loosen(p) }) + } + + const str = String(path) + const loose = str.replace(TRAILING_SLASH_REGEXP, '') + + // Preserve paths that consist entirely of slashes (e.g. '//') + // to prevent them from being reduced to an empty string, + // which would incorrectly match all paths. + return loose || str } diff --git a/test/router.js b/test/router.js index b440e40..1ccf06a 100644 --- a/test/router.js +++ b/test/router.js @@ -948,6 +948,72 @@ describe('Router', function () { ], done) }) + it('should not mount at single "/" when path is "//"', function (done) { + const router = new Router() + const server = createServer(router) + + router.use('//', saw) + router.use(helloWorld) + + series([ + function (cb) { + request(server) + .get('/') + .expect(200, 'hello, world', cb) + }, + function (cb) { + request(server) + .get('/foo') + .expect(200, 'hello, world', cb) + } + ], done) + }) + + it('should not mount at single "/" when path is "///"', function (done) { + const router = new Router() + const server = createServer(router) + + router.use('///', saw) + router.use(helloWorld) + + series([ + function (cb) { + request(server) + .get('/') + .expect(200, 'hello, world', cb) + }, + function (cb) { + request(server) + .get('/foo') + .expect(200, 'hello, world', cb) + } + ], done) + }) + + it('should not expose sub-router routes when mounted at "//"', function (done) { + const inner = new Router() + const router = new Router() + const server = createServer(router) + + inner.get('/', helloWorld) + inner.get('/admin', saw) + + router.use('//', inner) + + series([ + function (cb) { + request(server) + .get('/') + .expect(404, cb) + }, + function (cb) { + request(server) + .get('/admin') + .expect(404, cb) + } + ], done) + }) + it('should support array of paths', function (done) { const router = new Router() const server = createServer(router)