From 0b633cba32427e952d706a1a086b09dd1048a9ba Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 24 Jan 2024 17:09:33 +0100 Subject: [PATCH] [wrangler] fix: listen on loopback for wrangler dev port check and login The `wrangler dev` port availability check triggers a firewall prompt on macOS while it briefly opens and closes listeners. The OAuth callback server from `wrangler login` has the same issue. Fix both cases by listening on the loopback address only. Relates to #4430 --- .changeset/smart-owls-jog.md | 10 ++++++++++ packages/wrangler/src/dev.tsx | 13 ++++++++----- packages/wrangler/src/dev/proxy.ts | 2 +- packages/wrangler/src/user/user.ts | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 .changeset/smart-owls-jog.md diff --git a/.changeset/smart-owls-jog.md b/.changeset/smart-owls-jog.md new file mode 100644 index 0000000000000..59394205e8200 --- /dev/null +++ b/.changeset/smart-owls-jog.md @@ -0,0 +1,10 @@ +--- +"wrangler": patch +--- + +fix: listen on loopback for wrangler dev port check and login + +Avoid listening on the wildcard address to reduce the attacker's surface and +avoid firewall prompts on macOS. + +Relates to #4430. diff --git a/packages/wrangler/src/dev.tsx b/packages/wrangler/src/dev.tsx index b6f4859d370f1..f009031dcdd9e 100644 --- a/packages/wrangler/src/dev.tsx +++ b/packages/wrangler/src/dev.tsx @@ -626,12 +626,15 @@ export async function startApiDev(args: StartDevOptions) { }; } /** + * Get an available TCP port number. + * * Avoiding calling `getPort()` multiple times by memoizing the first result. */ -function memoizeGetPort(defaultPort?: number) { +function memoizeGetPort(defaultPort: number, listenHost: string) { let portValue: number; return async () => { - return portValue || (portValue = await getPort({ port: defaultPort })); + // Check a specific host to avoid probing all local addresses. + return portValue || (portValue = await getPort({ port: defaultPort, host: listenHost })); }; } /** @@ -705,14 +708,14 @@ async function validateDevServerSettings( ); const { zoneId, host, routes } = await getZoneIdHostAndRoutes(args, config); - const getLocalPort = memoizeGetPort(DEFAULT_LOCAL_PORT); - const getInspectorPort = memoizeGetPort(DEFAULT_INSPECTOR_PORT); + const getLocalPort = memoizeGetPort(DEFAULT_LOCAL_PORT, config.dev.ip); + const getInspectorPort = memoizeGetPort(DEFAULT_INSPECTOR_PORT, config.dev.ip); // Our inspector proxy server will be binding to the result of // `getInspectorPort`. If we attempted to bind workerd to the same inspector // port, we'd get a port already in use error. Therefore, generate a new port // for our runtime to bind its inspector service to. - const getRuntimeInspectorPort = memoizeGetPort(); + const getRuntimeInspectorPort = memoizeGetPort(0, config.dev.ip); if (config.services && config.services.length > 0) { logger.warn( diff --git a/packages/wrangler/src/dev/proxy.ts b/packages/wrangler/src/dev/proxy.ts index fe9fa3f8c6334..b37c9d95abc9f 100644 --- a/packages/wrangler/src/dev/proxy.ts +++ b/packages/wrangler/src/dev/proxy.ts @@ -686,7 +686,7 @@ export async function waitForPortToBeAvailable( doReject(err); } }); - server.listen(port, () => + server.listen(port, "localhost", () => terminator .terminate() .then(doResolve, () => diff --git a/packages/wrangler/src/user/user.ts b/packages/wrangler/src/user/user.ts index 90cc3a2fbbf25..f03ce3dbdc41c 100644 --- a/packages/wrangler/src/user/user.ts +++ b/packages/wrangler/src/user/user.ts @@ -1014,7 +1014,7 @@ export async function login( } }); - server.listen(8976); + server.listen(8976, "localhost"); }); if (props?.browser) { logger.log(`Opening a link in your default browser: ${urlToOpen}`);