@@ -34,7 +34,6 @@ var send = require('send');
34
34
var extname = path . extname ;
35
35
var resolve = path . resolve ;
36
36
var vary = require ( 'vary' ) ;
37
- var urlParse = require ( 'url' ) . parse ;
38
37
39
38
/**
40
39
* Response prototype.
@@ -50,6 +49,13 @@ var res = Object.create(http.ServerResponse.prototype)
50
49
51
50
module . exports = res
52
51
52
+ /**
53
+ * Module variables.
54
+ * @private
55
+ */
56
+
57
+ var schemaAndHostRegExp = / ^ (?: [ a - z A - Z ] [ a - z A - Z 0 - 9 + . - ] * : ) ? \/ \/ [ ^ \\ \/ \? ] + / ;
58
+
53
59
/**
54
60
* Set status `code`.
55
61
*
@@ -773,32 +779,23 @@ res.cookie = function (name, value, options) {
773
779
*/
774
780
775
781
res . location = function location ( url ) {
776
- var loc = String ( url ) ;
782
+ var loc ;
777
783
778
784
// "back" is an alias for the referrer
779
785
if ( url === 'back' ) {
780
786
loc = this . req . get ( 'Referrer' ) || '/' ;
787
+ } else {
788
+ loc = String ( url ) ;
781
789
}
782
790
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 ) ) ;
799
797
800
- // set location
801
- return this . set ( 'Location' , encodedUrl ) ;
798
+ return this . set ( 'Location' , loc ) ;
802
799
} ;
803
800
804
801
/**
0 commit comments