Repository navigation
fix: check the debug bind is loopback before claiming the port (#64 item 5) - #88
Merged
jason-shen merged 1 commit intoNov 7, 2026
Conversation
The loopback check ran after net.Listen, so a public debug.bind without allow_public really bound the port (and accepted into the backlog) until the check closed it. Parse and check the host first: an empty host is named as "every interface", an IP must be loopback, and a hostname must resolve to loopback addresses only. The post-Listen check stays as a backstop for hostnames that resolve differently at bind time. Addresses item 5 of streamcoreai#64. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses item 5 of #64: the loopback check now runs before the debug port is claimed.
Cause
startDebugServercallednet.Listenand only then checked whether the bound address was loopback. Sodebug.bind = "0.0.0.0:6060"withoutallow_publicreally bound the public port, accepting into the backlog, for the moment before the check closed it. That isn't an exposure, sinceServenever started. But a public port shouldn't be claimed at all, and":6060"got the vague "resolves to a non-loopback address".Change
checkLoopbackBindruns first whenallow_publicis false:net.SplitHostPortfailure →debug.bind "6060": missing port in address.":6060") → "listens on every interface; use 127.0.0.1 or set debug.allow_public = true …".net.Listenmay pick any of them).The post-
Listencheck stays as a backstop, since a hostname can resolve differently between the check and the bind.allow_public = trueskips both, as before. No config, docs or runtime-behaviour change for valid loopback binds.Item 5 only.
Tests
TestDebugServerRejectsPublicBindBeforeListeningholds a public port itself, then asks the debug server to bind it. A server that binds first fails with "address already in use". One that checks first returns theallow_publicguidance without touching the socket.TestDebugServerNamesAnAllInterfacesBind:":0"gets the "every interface" message.TestDebugServerRejectsAMalformedBind:"6060"gets adebug.bindparse error.TestDebugServerAcceptsLoopbackBinds:127.0.0.1:0,[::1]:0(skipped if the host has no IPv6 loopback) andlocalhost:0still start.Red proof, the same tests against
main(f16e44f):The first failure is the defect itself:
mainreachedbind()on the public port.Validation
The four CI commands (Linux, Go 1.27.3):
gofmt -l .clean,go build ./...clean,go vet ./...clean,go test -race ./...ok in all 15 packages with tests (internal/turnhas none).Prepared with AI assistance (Claude Code). I ran the checks above myself and the outputs are quoted as observed.