You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
router.use() silently accepts express() sub-apps without prototype restoration #7427
When an express() sub-app is mounted via router.use() instead of app.use(), the request and response prototypes are swapped by app.handle but never restored. The sub-app also never fires the mount event, so it does not inherit the parent's trust proxy setting. Any middleware that runs after the sub-app calls next() reads req.ip, req.secure, and req.hostname under the wrong app's trust policy, silently and without any error.
The only code that reverses this swap is the mounted_app closure built by app.use at lib/application.js:230-237. router.use never builds that closure, so the swap is permanent for the lifetime of the request.
The router already saves and restores request state across boundaries at index.js:171:
js
let done = restore(callback, req, 'baseUrl', 'next', 'params')
The prototype is simply not on the list.
Add proto (or Object.getPrototypeOf equivalents) to the restore call so the router's own cleanup undoes the prototype swap on every exit path — next(), next(err), and unhandled throws alike.
js
// index.js — inside Router.prototype.handle, before the loop
var reqProto = Object.getPrototypeOf(req)
var resProto = Object.getPrototypeOf(res)
This is expected. Mounting sub-apps works only on an Application object. The mount event docs mention that it is fired on a sub-app, when it is mounted on a parent app. Similarly app.use() docs mention sub-apps, but the docs for router.use() don't explicitly mention them (only "middleware functions").
Since router.use() does not expect an app object, it treats it as middleware. If middleware modifies the req/res objects, these modifications should persist.
Activity
krzysdz commentedon Aug 25, 2026
This is expected. Mounting sub-apps works only on an Application object. The
mountevent docs mention that it is fired on a sub-app, when it is mounted on a parent app. Similarlyapp.use()docs mention sub-apps, but the docs forrouter.use()don't explicitly mention them (only "middleware functions").Since
router.use()does not expect an app object, it treats it as middleware. If middleware modifies the req/res objects, these modifications should persist.Refs: