Skip to content

Commit 6a9633a

Browse files
committed
fix(dev): do not infer public mode from a non-loopback host
1 parent 27ad872 commit 6a9633a

4 files changed

Lines changed: 14 additions & 8 deletions

File tree

docs/dev.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ The `dev` command starts a development server with hot module replacement at [ht
5353
| `--clipboard` | `false` | Copy the URL to the clipboard |
5454
| `--qr` | | Print a QR code for the public URL (enabled by default when one is available) |
5555
| `--tunnel` | | Expose the server via a Cloudflare quick tunnel |
56-
| `--public` | | Listen on all network interfaces |
56+
| `--public` | | Listen on all network interfaces and allow any host to connect |
5757
| `--publicURL=<url>` | | Public URL to display (used for QR code and clipboard) |
5858
| `--https` | | Enable HTTPS with a locally-trusted development certificate |
5959
| `--https.cert=<path>` | | Path to TLS certificate |

packages/nuxt-cli/src/commands/dev.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ const command = defineCommand({
120120
},
121121
'public': {
122122
type: 'boolean',
123-
description: 'Listen on all network interfaces',
123+
description: 'Listen on all network interfaces and allow any host to connect',
124124
},
125125
'publicURL': {
126126
type: 'string',

packages/nuxt-cli/src/dev/utils.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
496496
res.statusCode = 403
497497
res.setHeader('Content-Type', 'text/plain')
498498
}
499-
res.end('Forbidden: this host is not allowed. Pass `--host` to allow it.')
499+
res.end('Forbidden: this host is not allowed. Pass it to `--host`, or `--public` to allow any host.')
500500
return true
501501
}
502502

@@ -1039,7 +1039,10 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
10391039

10401040
const hostname = overrides.hostname ?? nuxtConfig.devServer?.host
10411041

1042-
const isPublic = provider === 'codesandbox' || (overrides.public ?? (isPublicHostname(hostname) ? true : undefined))
1042+
// Only `--public` (or a sandbox that fronts the server) drops the `Host` and
1043+
// CORS checks. A non-loopback `--host` widens who can reach the bind, not
1044+
// which origins may read from it.
1045+
const isPublic = provider === 'codesandbox' || overrides.public
10431046

10441047
// `--https` (or its absence) wins over the config; `https.*` arguments and
10451048
// `devServer.https` options only apply once https is enabled.
@@ -1529,7 +1532,3 @@ function createConfigDirWatcher(cwd: string, onReload: (path: string) => void) {
15291532
configDirWatcher.close()
15301533
}
15311534
}
1532-
1533-
function isPublicHostname(hostname: string | undefined): boolean {
1534-
return !!hostname && !['localhost', '127.0.0.1', '::1'].includes(hostname)
1535-
}

packages/nuxt-cli/test/e2e/dev-allowed-hosts.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ describe('dev server allowed hosts', () => {
2626
expect(allowedHosts).toEqual(['127.0.0.1'])
2727
})
2828

29+
it('should keep the host allowlist for a non-loopback `--host`', { timeout: 120_000 }, async () => {
30+
const allowedHosts = await resolveAllowedHosts(['--host=0.0.0.0'])
31+
32+
expect(allowedHosts).not.toBe(true)
33+
expect(allowedHosts).toContain('localhost')
34+
})
35+
2936
it('should allow any host when the server is public', { timeout: 120_000 }, async () => {
3037
const allowedHosts = await resolveAllowedHosts(['--public'])
3138

0 commit comments

Comments
 (0)