@@ -35,6 +35,8 @@ function Server(compiler, options) {
35
35
this . headers = options . headers ;
36
36
this . clientLogLevel = options . clientLogLevel ;
37
37
this . clientOverlay = options . overlay ;
38
+ this . disableHostCheck = ! ! options . disableHostCheck ;
39
+ this . publicHost = options . public ;
38
40
this . sockets = [ ] ;
39
41
this . contentBaseWatchers = [ ] ;
40
42
@@ -52,6 +54,12 @@ function Server(compiler, options) {
52
54
// Init express server
53
55
const app = this . app = new express ( ) ;
54
56
57
+ app . all ( "*" , ( req , res , next ) => {
58
+ if ( this . checkHost ( req . headers ) )
59
+ return next ( ) ;
60
+ res . send ( "Invalid Host header" ) ;
61
+ } ) ;
62
+
55
63
// middleware for serving webpack bundle
56
64
this . middleware = webpackDevMiddleware ( compiler , options ) ;
57
65
@@ -389,8 +397,37 @@ Server.prototype.setContentHeaders = function(req, res, next) {
389
397
next ( ) ;
390
398
}
391
399
400
+ Server . prototype . checkHost = function ( headers ) {
401
+ // allow user to opt-out this security check, at own risk
402
+ if ( this . disableHostCheck ) return true ;
403
+
404
+ // get the Host header and extract hostname
405
+ // we don't care about port not matching
406
+ const hostHeader = headers . host ;
407
+ if ( ! hostHeader ) return false ;
408
+ const idx = hostHeader . indexOf ( ":" ) ;
409
+ const hostname = idx >= 0 ? hostHeader . substr ( 0 , idx ) : hostHeader ;
410
+
411
+ // always allow localhost host, for convience
412
+ if ( hostname === "127.0.0.1" || hostname === "localhost" ) return true ;
413
+
414
+ // allow hostname of listening adress
415
+ if ( hostname === this . listenHostname ) return true ;
416
+
417
+ // also allow public hostname if provided
418
+ if ( typeof this . publicHost === "string" ) {
419
+ const idxPublic = this . publicHost . indexOf ( ":" ) ;
420
+ const publicHostname = idxPublic >= 0 ? this . publicHost . substr ( 0 , idx ) : this . publicHost ;
421
+ if ( hostname === publicHostname ) return true ;
422
+ }
423
+
424
+ // disallow
425
+ return false ;
426
+ }
427
+
392
428
// delegate listen call and init sockjs
393
- Server . prototype . listen = function ( ) {
429
+ Server . prototype . listen = function ( port , hostname ) {
430
+ this . listenHostname = hostname ;
394
431
const returnValue = this . listeningApp . listen . apply ( this . listeningApp , arguments ) ;
395
432
const sockServer = sockjs . createServer ( {
396
433
// Use provided up-to-date sockjs-client
@@ -404,6 +441,11 @@ Server.prototype.listen = function() {
404
441
} ) ;
405
442
sockServer . on ( "connection" , ( conn ) => {
406
443
if ( ! conn ) return ;
444
+ if ( ! this . checkHost ( conn . headers ) ) {
445
+ this . sockWrite ( [ conn ] , "error" , "Invalid Host header" ) ;
446
+ conn . close ( ) ;
447
+ return ;
448
+ }
407
449
this . sockets . push ( conn ) ;
408
450
409
451
conn . on ( "close" , ( ) => {
0 commit comments