Skip to content

Commit 81e4e55

Browse files
authored
fix: migrate firewall to allowedHosts option (#3345)
1 parent a84ecd2 commit 81e4e55

17 files changed

+405
-238
lines changed

bin/cli-flags.js

+3-9
Original file line numberDiff line numberDiff line change
@@ -395,21 +395,15 @@ module.exports = {
395395
negative: true,
396396
},
397397
{
398-
name: 'firewall',
399-
type: [Boolean, String],
398+
name: 'allowed-hosts',
399+
type: String,
400400
configs: [
401-
{
402-
type: 'boolean',
403-
},
404401
{
405402
type: 'string',
406403
},
407404
],
408-
description:
409-
'Enable firewall or set hosts that are allowed to access the dev server.',
410-
negatedDescription: 'Disable firewall.',
405+
description: 'Set hosts that are allowed to access the dev server.',
411406
multiple: true,
412-
negative: true,
413407
},
414408
{
415409
name: 'watch-files',

examples/cli/web-socket-url/webpack.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ module.exports = setup({
1212
client: {
1313
webSocketURL: 'ws://localhost:8080',
1414
},
15-
firewall: false,
15+
allowedHosts: 'all',
1616
},
1717
});

lib/Server.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,8 @@ class Server {
899899

900900
checkHeaders(headers, headerToCheck) {
901901
// allow user to opt out of this security check, at their own risk
902-
// by explicitly disabling firewall
903-
if (!this.options.firewall) {
902+
// by explicitly enabling allowedHosts
903+
if (this.options.allowedHosts === 'all') {
904904
return true;
905905
}
906906

@@ -942,7 +942,7 @@ class Server {
942942
return true;
943943
}
944944

945-
const allowedHosts = this.options.firewall;
945+
const allowedHosts = this.options.allowedHosts;
946946

947947
// always allow localhost host, for convenience
948948
// allow if hostname is in allowedHosts

lib/options.json

+9-4
Original file line numberDiff line numberDiff line change
@@ -337,20 +337,25 @@
337337
"type": "object",
338338
"description": "Provide options to webpack-dev-middleware which handles webpack assets. https://webpack.js.org/configuration/dev-server/#devserverdevmiddleware"
339339
},
340-
"firewall": {
340+
"allowedHosts": {
341341
"anyOf": [
342342
{
343-
"type": "boolean"
343+
"enum": ["auto", "all"]
344+
},
345+
{
346+
"type": "string",
347+
"minLength": 1
344348
},
345349
{
346350
"type": "array",
347351
"items": {
348-
"type": "string"
352+
"type": "string",
353+
"minLength": 1
349354
},
350355
"minItems": 1
351356
}
352357
],
353-
"description": "Defines routes which are enabled by default, on by default and allows localhost. https://webpack.js.org/configuration/dev-server/#devserverfirewall"
358+
"description": "Defines routes which are enabled by default, on by default and allows localhost/value from the 'host' option/value from the 'client.webSocketURL' option. https://webpack.js.org/configuration/dev-server/#devserverallowedhosts"
354359
},
355360
"headers": {
356361
"anyOf": [

lib/utils/normalizeOptions.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,18 @@ function normalizeOptions(compiler, options, logger) {
128128

129129
options.devMiddleware = options.devMiddleware || {};
130130

131-
if (typeof options.firewall === 'undefined') {
132-
// firewall is enabled by default
133-
options.firewall = true;
131+
if (typeof options.allowedHosts === 'undefined') {
132+
// allowedHosts allows some default hosts picked from
133+
// `options.host` or `webSocketURL.host` and `localhost`
134+
options.allowedHosts = 'auto';
135+
}
136+
if (
137+
typeof options.allowedHosts === 'string' &&
138+
options.allowedHosts !== 'auto' &&
139+
options.allowedHosts !== 'all'
140+
) {
141+
// we store allowedHosts as array when supplied as string
142+
options.allowedHosts = [options.allowedHosts];
134143
}
135144

136145
if (typeof options.setupExitSignals === 'undefined') {

test/__snapshots__/validate-options.test.js.snap.webpack4

+39-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,44 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`options validate should throw an error on the "allowedHosts" option with '123' value 1`] = `
4+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
5+
- configuration.allowedHosts should be one of these:
6+
\\"auto\\" | \\"all\\" | non-empty string | [non-empty string, ...] (should not have fewer than 1 item)
7+
-> Defines routes which are enabled by default, on by default and allows localhost/value from the 'host' option/value from the 'client.webSocketURL' option. https://webpack.js.org/configuration/dev-server/#devserverallowedhosts
8+
Details:
9+
* configuration.allowedHosts should be one of these:
10+
\\"auto\\" | \\"all\\"
11+
* configuration.allowedHosts should be a non-empty string.
12+
* configuration.allowedHosts should be an array:
13+
[non-empty string, ...] (should not have fewer than 1 item)"
14+
`;
15+
16+
exports[`options validate should throw an error on the "allowedHosts" option with 'false' value 1`] = `
17+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
18+
- configuration.allowedHosts should be one of these:
19+
\\"auto\\" | \\"all\\" | non-empty string | [non-empty string, ...] (should not have fewer than 1 item)
20+
-> Defines routes which are enabled by default, on by default and allows localhost/value from the 'host' option/value from the 'client.webSocketURL' option. https://webpack.js.org/configuration/dev-server/#devserverallowedhosts
21+
Details:
22+
* configuration.allowedHosts should be one of these:
23+
\\"auto\\" | \\"all\\"
24+
* configuration.allowedHosts should be a non-empty string.
25+
* configuration.allowedHosts should be an array:
26+
[non-empty string, ...] (should not have fewer than 1 item)"
27+
`;
28+
29+
exports[`options validate should throw an error on the "allowedHosts" option with 'true' value 1`] = `
30+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
31+
- configuration.allowedHosts should be one of these:
32+
\\"auto\\" | \\"all\\" | non-empty string | [non-empty string, ...] (should not have fewer than 1 item)
33+
-> Defines routes which are enabled by default, on by default and allows localhost/value from the 'host' option/value from the 'client.webSocketURL' option. https://webpack.js.org/configuration/dev-server/#devserverallowedhosts
34+
Details:
35+
* configuration.allowedHosts should be one of these:
36+
\\"auto\\" | \\"all\\"
37+
* configuration.allowedHosts should be a non-empty string.
38+
* configuration.allowedHosts should be an array:
39+
[non-empty string, ...] (should not have fewer than 1 item)"
40+
`;
41+
342
exports[`options validate should throw an error on the "bonjour" option with '' value 1`] = `
443
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
544
- configuration.bonjour should be one of these:
@@ -141,22 +180,6 @@ exports[`options validate should throw an error on the "devMiddleware" option wi
141180
-> Provide options to webpack-dev-middleware which handles webpack assets. https://webpack.js.org/configuration/dev-server/#devserverdevmiddleware"
142181
`;
143182

144-
exports[`options validate should throw an error on the "firewall" option with '' value 1`] = `
145-
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
146-
- configuration.firewall should be one of these:
147-
boolean | [string, ...] (should not have fewer than 1 item)
148-
-> Defines routes which are enabled by default, on by default and allows localhost. https://webpack.js.org/configuration/dev-server/#devserverfirewall
149-
Details:
150-
* configuration.firewall should be a boolean.
151-
* configuration.firewall should be an array:
152-
[string, ...] (should not have fewer than 1 item)"
153-
`;
154-
155-
exports[`options validate should throw an error on the "firewall" option with '[]' value 1`] = `
156-
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
157-
- configuration.firewall should be an non-empty array."
158-
`;
159-
160183
exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
161184
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
162185
- configuration.headers should be one of these:

test/__snapshots__/validate-options.test.js.snap.webpack5

+39-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,44 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`options validate should throw an error on the "allowedHosts" option with '123' value 1`] = `
4+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
5+
- configuration.allowedHosts should be one of these:
6+
\\"auto\\" | \\"all\\" | non-empty string | [non-empty string, ...] (should not have fewer than 1 item)
7+
-> Defines routes which are enabled by default, on by default and allows localhost/value from the 'host' option/value from the 'client.webSocketURL' option. https://webpack.js.org/configuration/dev-server/#devserverallowedhosts
8+
Details:
9+
* configuration.allowedHosts should be one of these:
10+
\\"auto\\" | \\"all\\"
11+
* configuration.allowedHosts should be a non-empty string.
12+
* configuration.allowedHosts should be an array:
13+
[non-empty string, ...] (should not have fewer than 1 item)"
14+
`;
15+
16+
exports[`options validate should throw an error on the "allowedHosts" option with 'false' value 1`] = `
17+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
18+
- configuration.allowedHosts should be one of these:
19+
\\"auto\\" | \\"all\\" | non-empty string | [non-empty string, ...] (should not have fewer than 1 item)
20+
-> Defines routes which are enabled by default, on by default and allows localhost/value from the 'host' option/value from the 'client.webSocketURL' option. https://webpack.js.org/configuration/dev-server/#devserverallowedhosts
21+
Details:
22+
* configuration.allowedHosts should be one of these:
23+
\\"auto\\" | \\"all\\"
24+
* configuration.allowedHosts should be a non-empty string.
25+
* configuration.allowedHosts should be an array:
26+
[non-empty string, ...] (should not have fewer than 1 item)"
27+
`;
28+
29+
exports[`options validate should throw an error on the "allowedHosts" option with 'true' value 1`] = `
30+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
31+
- configuration.allowedHosts should be one of these:
32+
\\"auto\\" | \\"all\\" | non-empty string | [non-empty string, ...] (should not have fewer than 1 item)
33+
-> Defines routes which are enabled by default, on by default and allows localhost/value from the 'host' option/value from the 'client.webSocketURL' option. https://webpack.js.org/configuration/dev-server/#devserverallowedhosts
34+
Details:
35+
* configuration.allowedHosts should be one of these:
36+
\\"auto\\" | \\"all\\"
37+
* configuration.allowedHosts should be a non-empty string.
38+
* configuration.allowedHosts should be an array:
39+
[non-empty string, ...] (should not have fewer than 1 item)"
40+
`;
41+
342
exports[`options validate should throw an error on the "bonjour" option with '' value 1`] = `
443
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
544
- configuration.bonjour should be one of these:
@@ -141,22 +180,6 @@ exports[`options validate should throw an error on the "devMiddleware" option wi
141180
-> Provide options to webpack-dev-middleware which handles webpack assets. https://webpack.js.org/configuration/dev-server/#devserverdevmiddleware"
142181
`;
143182

144-
exports[`options validate should throw an error on the "firewall" option with '' value 1`] = `
145-
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
146-
- configuration.firewall should be one of these:
147-
boolean | [string, ...] (should not have fewer than 1 item)
148-
-> Defines routes which are enabled by default, on by default and allows localhost. https://webpack.js.org/configuration/dev-server/#devserverfirewall
149-
Details:
150-
* configuration.firewall should be a boolean.
151-
* configuration.firewall should be an array:
152-
[string, ...] (should not have fewer than 1 item)"
153-
`;
154-
155-
exports[`options validate should throw an error on the "firewall" option with '[]' value 1`] = `
156-
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
157-
- configuration.firewall should be an non-empty array."
158-
`;
159-
160183
exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
161184
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
162185
- configuration.headers should be one of these:

test/cli/__snapshots__/cli.test.js.snap.webpack4

+2-3
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,8 @@ Options:
271271
Page Applications.
272272
--compress Enable gzip compression.
273273
--no-compress Disable gzip compression.
274-
--firewall [value...] Enable firewall or set hosts that are
275-
allowed to access the dev server.
276-
--no-firewall Disable firewall.
274+
--allowed-hosts <value...> Set hosts that are allowed to access the dev
275+
server.
277276
--watch-files <value...> Watch static files for file changes.
278277

279278
Global options:

test/cli/__snapshots__/cli.test.js.snap.webpack5

+2-3
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,8 @@ Options:
272272
Page Applications.
273273
--compress Enable gzip compression.
274274
--no-compress Disable gzip compression.
275-
--firewall [value...] Enable firewall or set hosts that are
276-
allowed to access the dev server.
277-
--no-firewall Disable firewall.
275+
--allowed-hosts <value...> Set hosts that are allowed to access the dev
276+
server.
278277
--watch-files <value...> Watch static files for file changes.
279278

280279
Global options:

test/cli/cli.test.js

+43
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,49 @@ describe('CLI', () => {
654654
.catch(done);
655655
});
656656

657+
describe('allowed-hosts', () => {
658+
it('--allowed-hosts auto', (done) => {
659+
testBin(['--allowed-hosts', 'auto'])
660+
.then((output) => {
661+
expect(output.exitCode).toEqual(0);
662+
done();
663+
})
664+
.catch(done);
665+
});
666+
667+
it('--allowed-hosts all', (done) => {
668+
testBin(['--allowed-hosts', 'all'])
669+
.then((output) => {
670+
expect(output.exitCode).toEqual(0);
671+
done();
672+
})
673+
.catch(done);
674+
});
675+
676+
it('--allowed-hosts string', (done) => {
677+
testBin(['--allowed-hosts', 'testhost.com'])
678+
.then((output) => {
679+
expect(output.exitCode).toEqual(0);
680+
done();
681+
})
682+
.catch(done);
683+
});
684+
685+
it('--allowed-hosts multiple', (done) => {
686+
testBin([
687+
'--allowed-hosts',
688+
'testhost.com',
689+
'--allowed-hosts',
690+
'testhost1.com',
691+
])
692+
.then((output) => {
693+
expect(output.exitCode).toEqual(0);
694+
done();
695+
})
696+
.catch(done);
697+
});
698+
});
699+
657700
it('--no-static-serve-index', (done) => {
658701
testBin('--no-static-serve-index')
659702
.then((output) => {

test/e2e/web-socket-server-and-url.test.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ for (const webSocketServerType of webSocketServerTypes) {
6565
webSocketServer: webSocketServerType,
6666
port: devServerPort,
6767
host: devServerHost,
68-
firewall: false,
68+
allowedHosts: 'all',
6969
hot: true,
7070
};
7171

@@ -132,7 +132,7 @@ for (const webSocketServerType of webSocketServerTypes) {
132132
webSocketServer: webSocketServerType,
133133
port: devServerPort,
134134
host: devServerHost,
135-
firewall: false,
135+
allowedHosts: 'all',
136136
hot: true,
137137
};
138138

@@ -204,7 +204,7 @@ for (const webSocketServerType of webSocketServerTypes) {
204204
port: devServerPort,
205205
host: devServerHost,
206206
webSocketServer: webSocketServerType,
207-
firewall: false,
207+
allowedHosts: 'all',
208208
hot: true,
209209
static: true,
210210
};

0 commit comments

Comments
 (0)