Skip to content

Commit 6415f70

Browse files
committedMar 25, 2024
Merge tag '4.19.2' into 5.0
4.19.2
2 parents 416ba02 + 04bc627 commit 6415f70

File tree

3 files changed

+287
-64
lines changed

3 files changed

+287
-64
lines changed
 

‎History.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
5.x
22
===
33

4-
This incorporates all changes after 4.17.2 up to 4.19.1.
4+
This incorporates all changes after 4.17.2 up to 4.19.2.
55

66
5.0.0-beta.1 / 2022-02-14
77
=========================
@@ -162,6 +162,11 @@ This is the first Express 5.0 alpha release, based off 4.10.1.
162162
* add:
163163
- `app.router` is a reference to the base router
164164

165+
4.19.2 / 2024-03-25
166+
==========
167+
168+
* Improved fix for open redirect allow list bypass
169+
165170
4.19.1 / 2024-03-20
166171
==========
167172

‎lib/response.js

+17-20
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ var send = require('send');
3434
var extname = path.extname;
3535
var resolve = path.resolve;
3636
var vary = require('vary');
37-
var urlParse = require('url').parse;
3837

3938
/**
4039
* Response prototype.
@@ -50,6 +49,13 @@ var res = Object.create(http.ServerResponse.prototype)
5049

5150
module.exports = res
5251

52+
/**
53+
* Module variables.
54+
* @private
55+
*/
56+
57+
var schemaAndHostRegExp = /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?\/\/[^\\\/\?]+/;
58+
5359
/**
5460
* Set status `code`.
5561
*
@@ -773,32 +779,23 @@ res.cookie = function (name, value, options) {
773779
*/
774780

775781
res.location = function location(url) {
776-
var loc = String(url);
782+
var loc;
777783

778784
// "back" is an alias for the referrer
779785
if (url === 'back') {
780786
loc = this.req.get('Referrer') || '/';
787+
} else {
788+
loc = String(url);
781789
}
782790

783-
var lowerLoc = loc.toLowerCase();
784-
var encodedUrl = encodeUrl(loc);
785-
if (lowerLoc.indexOf('https://') === 0 || lowerLoc.indexOf('http://') === 0) {
786-
try {
787-
var parsedUrl = urlParse(loc);
788-
var parsedEncodedUrl = urlParse(encodedUrl);
789-
// Because this can encode the host, check that we did not change the host
790-
if (parsedUrl.host !== parsedEncodedUrl.host) {
791-
// If the host changes after encodeUrl, return the original url
792-
return this.set('Location', loc);
793-
}
794-
} catch (e) {
795-
// If parse fails, return the original url
796-
return this.set('Location', loc);
797-
}
798-
}
791+
var m = schemaAndHostRegExp.exec(loc);
792+
var pos = m ? m[0].length + 1 : 0;
793+
794+
// Only encode after host to avoid invalid encoding which can introduce
795+
// vulnerabilities (e.g. `\\` to `%5C`).
796+
loc = loc.slice(0, pos) + encodeUrl(loc.slice(pos));
799797

800-
// set location
801-
return this.set('Location', encodedUrl);
798+
return this.set('Location', loc);
802799
};
803800

804801
/**

0 commit comments

Comments
 (0)