@@ -35,6 +35,8 @@ function Server(compiler, options) {
3535 this . headers = options . headers ;
3636 this . clientLogLevel = options . clientLogLevel ;
3737 this . clientOverlay = options . overlay ;
38+ this . disableHostCheck = ! ! options . disableHostCheck ;
39+ this . publicHost = options . public ;
3840 this . sockets = [ ] ;
3941 this . contentBaseWatchers = [ ] ;
4042
@@ -52,6 +54,12 @@ function Server(compiler, options) {
5254 // Init express server
5355 const app = this . app = new express ( ) ;
5456
57+ app . all ( "*" , ( req , res , next ) => {
58+ if ( this . checkHost ( req . headers ) )
59+ return next ( ) ;
60+ res . send ( "Invalid Host header" ) ;
61+ } ) ;
62+
5563 // middleware for serving webpack bundle
5664 this . middleware = webpackDevMiddleware ( compiler , options ) ;
5765
@@ -389,8 +397,37 @@ Server.prototype.setContentHeaders = function(req, res, next) {
389397 next ( ) ;
390398}
391399
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+
392428// delegate listen call and init sockjs
393- Server . prototype . listen = function ( ) {
429+ Server . prototype . listen = function ( port , hostname ) {
430+ this . listenHostname = hostname ;
394431 const returnValue = this . listeningApp . listen . apply ( this . listeningApp , arguments ) ;
395432 const sockServer = sockjs . createServer ( {
396433 // Use provided up-to-date sockjs-client
@@ -404,6 +441,11 @@ Server.prototype.listen = function() {
404441 } ) ;
405442 sockServer . on ( "connection" , ( conn ) => {
406443 if ( ! conn ) return ;
444+ if ( ! this . checkHost ( conn . headers ) ) {
445+ this . sockWrite ( [ conn ] , "error" , "Invalid Host header" ) ;
446+ conn . close ( ) ;
447+ return ;
448+ }
407449 this . sockets . push ( conn ) ;
408450
409451 conn . on ( "close" , ( ) => {
0 commit comments