fix(cli): go-code starts harnessd on loopback so the bind guard admits it - #1412
Conversation
…s it
`go-code` could not start on any machine without an API key store. The
wrapper spawned its daemon with HARNESS_ADDR=":${port}" — an empty host,
meaning every interface — and cmd/harnessd/bind_guard.go (#1328) refuses
to start an unauthenticated daemon that listens beyond loopback. The
daemon exited, and the wrapper reported the port was probably in use,
which was never the cause.
The wrapper's client base URL has always been http://127.0.0.1:${port},
so the wide bind had no consumer. It only published an unauthenticated
agent-execution service to the local network, reachable by anyone on the
LAN with the user's provider credentials. Binding loopback restores the
entry point and closes that exposure.
Also corrects the failure hint to point at the harnessd log rather than
asserting port contention, and documents that HARNESS_ADDR supplies only
the port to the wrapper.
Closes #1411
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJGxhoFhA8JjkwZFcLGdS5
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5146d547dd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -1,5 +1,39 @@ | |||
| # Engineering Log | |||
|
|
|||
| ## 2026-09-08 — Issue #1411 go-code wrapper bound harnessd beyond loopback | |||
There was a problem hiding this comment.
Record this issue's success criteria in the durable log
This runtime fix documents Issue #1411 only in the engineering log; docs/logs/long-term-thinking-log.md has no corresponding command intent, user intent, or success definition. Add or update that durable entry so future work retains the required criteria instead of relying on commit or issue history alone.
AGENTS.md reference: AGENTS.md:L17-L23
Useful? React with 👍 / 👎.
Closes #1411
The bug
Plain
go-codewas dead on any machine with no API key store configured and noHARNESS_AUTH_DISABLEDset — which is the state a new user is in right afterbrew install --HEADor./scripts/install.sh. The README presentsgo-codeas the way to use this project, so the primary entry point did not work out of the box.Cause
scripts/go-code.shstart_server()spawned the daemon withHARNESS_ADDR=":${port}". An empty host means every interface, andcmd/harnessd/bind_guard.go(#1328) refuses to start an unauthenticated daemon that listens beyond loopback, so the daemon exited before the health check.The hint the wrapper then printed was wrong twice over: the port was not in use, and neither suggested remedy could work, because the wrapper keeps only
${addr##*:}fromHARNESS_ADDRand always re-bound:PORT.Fix
Bind
127.0.0.1:${port}. The wrapper's client base URL has always beenhttp://127.0.0.1:${port}, so the wildcard bind never had a consumer — it only published an unauthenticated agent-execution service to the local network, where anyone who could reach the port could start runs in the user's workspace with the user's provider credentials. This is strictly tightening: the guard turned that silent exposure into a loud startup failure, and this closes it properly rather than relaxing the guard or disabling auth.Also in scope: the misleading failure hint now points at the harnessd log above it, and the header comment plus
--helptext state thatHARNESS_ADDRsupplies only the port.Deliberately left alone:
scripts/soak.sh,scripts/smoke-test.sh, andscripts/run-bench-smoke.shalso bind:${PORT}, but all three passHARNESS_AUTH_DISABLED=true, so the guard admits them. #1392 tracks the sibling instance ininternal/workspace/bootstrap.go:36, which needs a different remedy (a VM daemon genuinely needs a reachable bind plus auth) and stays separate.Verification
Regression test first.
TestGoCodeScriptStartsHarnessdOnLoopbackrecords the address the wrapper hands its daemon and asserts it is127.0.0.1:19282whenHARNESS_ADDR=:19282— pinning the invariant at the seam, and keeping the port assertion so a fix that hardcodes127.0.0.1:8080fails too.Red before the fix:
Green after, together with the two existing wrapper tests (
go test ./cmd/harnesscli -run TestGoCodeScript).Real path, not just the unit test — the actual wrapper starting a real daemon, no stubs:
The listener is on loopback and the run listing came back, where before the fix the same command killed the daemon at startup. The corrected hint also proved itself incidentally: an unrelated stray-daemon workspace-lock failure surfaced during testing, and the new message sent me to the harnessd log instead of hunting a port conflict.
🤖 Generated with Claude Code
https://claude.ai/code/session_01WJGxhoFhA8JjkwZFcLGdS5