Skip to content

Commit

Permalink
feat(@angular/cli): add host check flags to ng serve
Browse files Browse the repository at this point in the history
Two new flags are added to `ng serve`:
- `--public-host` (aliased by `--live-reload-client): Specify the URL that the browser client will use.
- `--disable-host-check`: Don't verify connected clients are part of allowed hosts.

Setting `--disable-host-check` will output a warning:
```
WARNING Running a server with --disable-host-check is a security risk. See https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a for more information.
```

See #6070 for more context about this change.

Fix #6070
  • Loading branch information
filipesilva committed May 9, 2017
1 parent 5a41c42 commit a54a991
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 14 deletions.
16 changes: 13 additions & 3 deletions docs/documentation/serve.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,22 @@ All the build Options are available in serve, below are the additional options.
</details>

<details>
<summary>live-reload-client</summary>
<summary>public-host</summary>
<p>
<code>--live-reload-client</code>
<code>--public-host</code> (aliases: <code>--live-reload-client</code>)
</p>
<p>
Specify the URL that the live reload browser client will use.
Specify the URL that the browser client will use.
</p>
</details>

<details>
<summary>disable-host-check</summary>
<p>
<code>--disable-host-check</code> <em>default value: false</em>
</p>
<p>
Don't verify connected clients are part of allowed hosts.
</p>
</details>

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"walk-sync": "^0.3.1",
"webpack": "~2.4.0",
"webpack-dev-middleware": "^1.10.2",
"webpack-dev-server": "~2.4.2",
"webpack-dev-server": "~2.4.5",
"webpack-merge": "^2.4.0",
"zone.js": "^0.8.4"
},
Expand Down
14 changes: 11 additions & 3 deletions packages/@angular/cli/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export interface ServeTaskOptions extends BuildOptions {
host?: string;
proxyConfig?: string;
liveReload?: boolean;
liveReloadClient?: string;
publicHost?: string;
disableHostCheck?: boolean;
ssl?: boolean;
sslKey?: string;
sslCert?: string;
Expand Down Expand Up @@ -84,9 +85,16 @@ export const baseServeCommandOptions: any = overrideOptions([
description: 'Whether to reload the page on change, using live-reload.'
},
{
name: 'live-reload-client',
name: 'public-host',
type: String,
description: 'Specify the URL that the live reload browser client will use.'
aliases: ['live-reload-client'],
description: 'Specify the URL that the browser client will use.'
},
{
name: 'disable-host-check',
type: Boolean,
default: false,
description: 'Don\'t verify connected clients are part of allowed hosts.',
},
{
name: 'hmr',
Expand Down
2 changes: 2 additions & 0 deletions packages/@angular/cli/custom-typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ interface IWebpackDevServerConfigurationOptions {
key?: string;
cert?: string;
overlay?: boolean | { errors: boolean, warnings: boolean };
public?: string;
disableHostCheck?: boolean;
}
2 changes: 1 addition & 1 deletion packages/@angular/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"walk-sync": "^0.3.1",
"webpack": "~2.4.0",
"webpack-dev-middleware": "^1.10.2",
"webpack-dev-server": "~2.4.2",
"webpack-dev-server": "~2.4.5",
"webpack-merge": "^2.4.0",
"zone.js": "^0.8.4"
},
Expand Down
21 changes: 16 additions & 5 deletions packages/@angular/cli/tasks/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,18 @@ export default Task.extend({
hostname: serveTaskOptions.host === '0.0.0.0' ? 'localhost' : serveTaskOptions.host,
port: serveTaskOptions.port.toString()
});

if (serveTaskOptions.disableHostCheck) {
ui.writeLine(oneLine`
${chalk.yellow('WARNING')} Running a server with --disable-host-check is a security risk.
See https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
for more information.
`);
}

let clientAddress = serverAddress;
if (serveTaskOptions.liveReloadClient) {
const clientUrl = url.parse(serveTaskOptions.liveReloadClient);
if (serveTaskOptions.publicHost) {
const clientUrl = url.parse(serveTaskOptions.publicHost);
// very basic sanity check
if (!clientUrl.host) {
return Promise.reject(new SilentError(`'live-reload-client' must be a full URL.`));
Expand Down Expand Up @@ -96,7 +105,7 @@ export default Task.extend({
webpackConfig.plugins.unshift({
apply: (compiler: any) => {
compiler.plugin('after-environment', () => {
compiler.watchFileSystem = { watch: () => {} };
compiler.watchFileSystem = { watch: () => { } };
});
}
});
Expand Down Expand Up @@ -153,7 +162,9 @@ export default Task.extend({
errors: serveTaskOptions.target === 'development',
warnings: false
},
contentBase: false
contentBase: false,
public: serveTaskOptions.publicHost,
disableHostCheck: serveTaskOptions.disableHostCheck
};

if (sslKey != null && sslCert != null) {
Expand Down Expand Up @@ -193,7 +204,7 @@ export default Task.extend({
return reject(err);
}
if (serveTaskOptions.open) {
opn(serverAddress);
opn(serverAddress);
}
});
})
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/tests/misc/live-reload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function () {
// Serve with live reload client set to api should call api.
.then(_ => silentExecAndWaitForOutputToMatch(
'ng',
['e2e', '--watch', `--live-reload-client=${apiUrl}`],
['e2e', '--watch', `--public-host=${apiUrl}`],
protractorGoodRegEx
))
.then(_ => wait(2000))
Expand Down
43 changes: 43 additions & 0 deletions tests/e2e/tests/misc/public-host.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as os from 'os';
import * as _ from 'lodash';

import { request } from '../../utils/http';
import { killAllProcesses } from '../../utils/process';
import { ngServe } from '../../utils/project';

export default function () {
const firstLocalIp = _(os.networkInterfaces())
.values()
.flatten()
.filter({ family: 'IPv4', internal: false })
.map('address')
.first();
const publicHost = `${firstLocalIp}:4200`;
const localAddress = `http://${publicHost}`;

return Promise.resolve()
.then(() => ngServe('--host=0.0.0.0'))
.then(() => request(localAddress))
.then(body => {
if (!body.match(/Invalid Host header/)) {
throw new Error('Response does not match expected value.');
}
})
.then(() => killAllProcesses(), (err) => { killAllProcesses(); throw err; })
.then(() => ngServe('--host=0.0.0.0', `--public-host=${publicHost}`))
.then(() => request(localAddress))
.then(body => {
if (!body.match(/<app-root><\/app-root>/)) {
throw new Error('Response does not match expected value.');
}
})
.then(() => killAllProcesses(), (err) => { killAllProcesses(); throw err; })
.then(() => ngServe('--host=0.0.0.0', `--disable-host-check`))
.then(() => request(localAddress))
.then(body => {
if (!body.match(/<app-root><\/app-root>/)) {
throw new Error('Response does not match expected value.');
}
})
.then(() => killAllProcesses(), (err) => { killAllProcesses(); throw err; });
}

0 comments on commit a54a991

Please sign in to comment.