router.use() silently accepts express() sub-apps without prototype restoration
- Dominant language
- JavaScript
- Stars
- 69.5k
- Forks
- 25k
- Avg merge
- 4d 20h
- Merged PRs (30d)
- 9
Description
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.
app.handle (lib/application.js:169-170) performs:
js
Object.setPrototypeOf(req, this.request)
Object.setPrototypeOf(res, this.response)
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)
var done = restore(callback, req, 'baseUrl', 'next', 'params')
var _done = done
done = function(err) {
Object.setPrototypeOf(req, reqProto)
Object.setPrototypeOf(res, resProto)
_done(err)
}
Contributor guide
Research direction
Read lib/application.js:169-170 and 230-237, then trace Router.prototype.handle in index.js around line 171 and its restore callback. Verify that request and response prototypes are restored after next(), next(err), and unhandled throws, and that later middleware reads req.ip, req.secure, and req.hostname under the original app’s trust policy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- express, javascript, node.js
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100