Skip to content

Commit

Permalink
[wrangler] fix: listen on loopback for wrangler dev port check and login
Browse files Browse the repository at this point in the history
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 cloudflare#4430
  • Loading branch information
Lekensteyn committed Jan 24, 2024
1 parent f4f38fc commit 3685a0f
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 7 deletions.
10 changes: 10 additions & 0 deletions .changeset/smart-owls-jog.md
Original file line number Diff line number Diff line change
@@ -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.
13 changes: 8 additions & 5 deletions packages/wrangler/src/dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }));
};
}
/**
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/src/dev/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ export async function waitForPortToBeAvailable(
doReject(err);
}
});
server.listen(port, () =>
server.listen(port, "localhost", () =>
terminator
.terminate()
.then(doResolve, () =>
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/src/user/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`);
Expand Down

0 comments on commit 3685a0f

Please sign in to comment.