Skip to content

fix(cli): go-code starts harnessd on loopback so the bind guard admits it - #1412

Merged
dennisonbertram merged 1 commit into
mainfrom
fix/1411-go-code-loopback-bind
Sep 8, 2026
Merged

fix(cli): go-code starts harnessd on loopback so the bind guard admits it#1412
dennisonbertram merged 1 commit into
mainfrom
fix/1411-go-code-loopback-bind

Conversation

@dennisonbertram

Copy link
Copy Markdown
Owner

Closes #1411

The bug

Plain go-code was dead on any machine with no API key store configured and no HARNESS_AUTH_DISABLED set — which is the state a new user is in right after brew install --HEAD or ./scripts/install.sh. The README presents go-code as the way to use this project, so the primary entry point did not work out of the box.

[go-code] no server at http://127.0.0.1:8080, starting harnessd on port 8080
[go-code] waiting for server to become healthy (pid 55263)...
2026/09/08 06:35:44 fatal: refusing to start: :8080 listens beyond this machine but no
authentication is configured, ...
[go-code] ERROR: harnessd (pid 55263) exited before becoming healthy on port 8080. If the
port is already in use (see the harnessd log above), free it or run on another port ...

Cause

scripts/go-code.sh start_server() spawned the daemon with HARNESS_ADDR=":${port}". An empty host means every interface, and cmd/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##*:} from HARNESS_ADDR and always re-bound :PORT.

Fix

Bind 127.0.0.1:${port}. The wrapper's client base URL has always been http://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 --help text state that HARNESS_ADDR supplies only the port.

Deliberately left alone: scripts/soak.sh, scripts/smoke-test.sh, and scripts/run-bench-smoke.sh also bind :${PORT}, but all three pass HARNESS_AUTH_DISABLED=true, so the guard admits them. #1392 tracks the sibling instance in internal/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. TestGoCodeScriptStartsHarnessdOnLoopback records the address the wrapper hands its daemon and asserts it is 127.0.0.1:19282 when HARNESS_ADDR=:19282 — pinning the invariant at the seam, and keeping the port assertion so a fix that hardcodes 127.0.0.1:8080 fails too.

Red before the fix:

--- FAIL: TestGoCodeScriptStartsHarnessdOnLoopback (0.38s)
    go_code_script_test.go:200: harnessd bind address = ":19282", want "127.0.0.1:19282"

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:

$ HARNESS_ADDR=:19399 bash scripts/go-code.sh runs
run_24cad1e9-...  completed  gpt-4.1-mini  it's been more than 15 seconds.
...
[go-code] stopping harnessd (pid 93270)
$ echo $?
0
$ lsof -nP -iTCP:19399 -sTCP:LISTEN     # sampled while running
harnessd  TCP  127.0.0.1:19399

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

…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
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-08T10:50:04.799908Z 5146d54 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@dennisonbertram
dennisonbertram merged commit 7af7aae into main Sep 8, 2026
2 checks passed
@dennisonbertram
dennisonbertram deleted the fix/1411-go-code-loopback-bind branch September 8, 2026 10:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

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.

[Bug]: go-code cannot start — wrapper binds harnessd to :PORT and the bind guard refuses it

1 participant