Skip to content

fix(cli): scope the serve port guard to the bind address - #15472

Merged
diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.52from
HouMinXi:fix/15424-port-guard
Oct 6, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.52from
HouMinXi:fix/15424-port-guard

Conversation

@HouMinXi

@HouMinXi HouMinXi commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • omniroute serve treated every listener on the port as a conflict. lsof -t does not say which address is listening, so a forwarder bound to another address stopped a loopback serve (OMNIROUTE_SERVER_HOST=127.0.0.1).
  • Discovery now keeps the listen address. A listener on a different specific address does not block the bind. A wildcard (*, 0.0.0.0, ::) still does, because that bind holds loopback too.
  • The port is the full token after the colon. 1443 is not a match for 443. A line with no listen address is not a conflict.
  • When the bind host is a specific address, the fallback probe listens on that address only. The default host is still 0.0.0.0, and that path still probes every address.
  • Related to fix(startup): 3.8.51 serve pre-flight port guard refuses to start when an unrelated listener holds the same port on another address #15424

Validation

  • node --test tests/unit/cli-serve-port-in-use-preflight.test.mjs tests/unit/cli-serve-stop-command.test.ts tests/unit/cli-serve-hostname.test.ts — 35 pass, 0 fail
  • Removing the empty-name guard makes the 1443 vs 443 test fail. Putting it back passes.
  • Forge review on the uncommitted diff, two separate LOCAL runs, review-default. Both ended PENDING with 0 CONFIRMED. The UNCERTAIN notes are excerpt line counts (declared N, carried N-1) and restatements of the address filter. The line-count note moved between line ranges across runs and did not name a behavior change.

Tests Added Or Updated

  • tests/unit/cli-serve-port-in-use-preflight.test.mjs
    • loopback bind ignores a listener on 192.168.1.50
    • loopback bind still reports a *:port listener
    • 127.0.0.1:1443 is not a listener on port 443
    • lsof is called without -t so the address stays in the output

Coverage Notes

  • The new tests stub lsof stdout. They do not open a real socket on a second address. The existing probe tests still bind a real port.

Reviewer Notes

  • stop still uses lsof -t. It kills listeners; it does not decide whether a bind would succeed.
  • Default resolveServerHost() is 0.0.0.0. With no OMNIROUTE_SERVER_HOST, every listener is still a conflict.

lsof -t reports every listener on the port, so a forwarder on another
address blocked a loopback serve. Keep the listen address and ignore a
listener that does not hold the address serve will bind. A wildcard
still blocks loopback. The port after the colon must match exactly, so
1443 is not 443. A missing name is not a conflict.

Related to diegosouzapw#15424.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
@HouMinXi
HouMinXi requested a review from diegosouzapw as a code owner October 3, 2026 18:31
The bind-address guard needs its own changelog fragment so release
aggregation picks it up.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
@diegosouzapw
diegosouzapw merged commit 58269a7 into diegosouzapw:release/v3.8.52 Oct 6, 2026
43 of 51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants