Skip to content

Commit 762a509

Browse files
committed
Merge branch 'security/host-check-webpack-1' into webpack-1
2 parents 59348b2 + eb5eaab commit 762a509

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

client/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ var onSocketMsg = {
8282
log("error", stripAnsi(errors[i]));
8383
if(initial) return initial = false;
8484
},
85+
error: function(error) {
86+
console.error(error);
87+
},
8588
close: function() {
8689
log("error", "[WDS] Disconnected!");
8790
}

lib/Server.js

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ function Server(compiler, options) {
2222
this.hot = options.hot;
2323
this.headers = options.headers;
2424
this.clientLogLevel = options.clientLogLevel;
25+
this.disableHostCheck = !!options.disableHostCheck;
26+
this.publicHost = options.public;
2527
this.sockets = [];
2628

2729
// Listening for events
@@ -50,6 +52,12 @@ function Server(compiler, options) {
5052
// Init express server
5153
var app = this.app = new express();
5254

55+
app.all("*", (req, res, next) => {
56+
if(this.checkHost(req.headers))
57+
return next();
58+
res.send("Invalid Host header");
59+
});
60+
5361
// middleware for serving webpack bundle
5462
this.middleware = webpackDevMiddleware(compiler, options);
5563

@@ -319,8 +327,37 @@ Server.prototype.setContentHeaders = function(req, res, next) {
319327
next();
320328
}
321329

330+
Server.prototype.checkHost = function(headers) {
331+
// allow user to opt-out this security check, at own risk
332+
if(this.disableHostCheck) return true;
333+
334+
// get the Host header and extract hostname
335+
// we don't care about port not matching
336+
const hostHeader = headers.host;
337+
if(!hostHeader) return false;
338+
const idx = hostHeader.indexOf(":");
339+
const hostname = idx >= 0 ? hostHeader.substr(0, idx) : hostHeader;
340+
341+
// always allow localhost host, for convience
342+
if(hostname === "127.0.0.1" || hostname === "localhost") return true;
343+
344+
// allow hostname of listening adress
345+
if(hostname === this.listenHostname) return true;
346+
347+
// also allow public hostname if provided
348+
if(typeof this.publicHost === "string") {
349+
const idxPublic = this.publicHost.indexOf(":");
350+
const publicHostname = idxPublic >= 0 ? this.publicHost.substr(0, idx) : this.publicHost;
351+
if(hostname === publicHostname) return true;
352+
}
353+
354+
// disallow
355+
return false;
356+
}
357+
322358
// delegate listen call and init sockjs
323-
Server.prototype.listen = function() {
359+
Server.prototype.listen = function(port, hostname) {
360+
this.listenHostname = hostname;
324361
this.listeningApp.listen.apply(this.listeningApp, arguments);
325362
var sockServer = sockjs.createServer({
326363
// Limit useless logs
@@ -332,6 +369,11 @@ Server.prototype.listen = function() {
332369
});
333370
sockServer.on("connection", function(conn) {
334371
if(!conn) return;
372+
if(!this.checkHost(conn.headers)) {
373+
this.sockWrite([conn], "error", "Invalid Host header");
374+
conn.close();
375+
return;
376+
}
335377
this.sockets.push(conn);
336378

337379
conn.on("close", function() {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"stream-cache": "~0.0.1",
1919
"strip-ansi": "^3.0.0",
2020
"supports-color": "^3.1.1",
21-
"webpack-dev-middleware": "^1.4.0",
21+
"webpack-dev-middleware": "^1.10.2",
2222
"http-proxy-middleware": "~0.17.1"
2323
},
2424
"devDependencies": {

0 commit comments

Comments
 (0)