Uh oh!
There was an error while loading. Please reload this page.
Bind the OAuth callback listener to an ephemeral loopback port (RFC 8252 §7.3) - #356
Merged
Merged
Conversation
…252 §7.3) hey auth login listened on a fixed 127.0.0.1:8976, so any local process holding that port could keep the CLI from ever signing in, and the redirect_uri was a constant. Now the listener binds 127.0.0.1:0 before the authorization URL is built and the redirect_uri carries whichever port the kernel handed out, for both the authorization request and the token exchange. Hygiene only: a local process picks its own port either way, so this is not what stops loopback impersonation; PKCE is. Requires the HEY server to accept any port for the CLI's loopback client (haystack: OAuth loopback redirect_uri matching), which deploys first and stays compatible with the fixed port until this ships.
Contributor
There was a problem hiding this comment.
Pull request overview
Binds OAuth callbacks to an ephemeral loopback port and consistently uses the assigned port throughout the PKCE flow.
Changes:
- Moves listener creation into
Login. - Passes the bound listener to callback handling.
- Updates tests and authentication documentation.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
internal/auth/auth.go | Uses an ephemeral callback port. |
internal/auth/auth_test.go | Verifies listener binding, redirect URI consistency, and failures. |
AGENTS.md | Documents ephemeral callback ports. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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 freeto 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.
What
hey auth loginbinds its OAuth callback listener to127.0.0.1:0instead of the fixed127.0.0.1:8976, and theredirect_urisent in both the authorization request and the token exchange carries whichever port the kernel handed out. The listener is bound before the authorization URL is built so the URL can name the real port;Loginowns the listener andwaitForCallbackserves on it.Why
RFC 8252 §7.3. A fixed port lets any local process squat
127.0.0.1:8976and block the CLI from ever signing in. Hygiene / DoS-resistance only — a local process picks its own port either way, so this is not what stops loopback impersonation; PKCE is. Tracked on Security Hardening card 10248717570 (item 6 of the H1 #3945131 plan).Depends on
basecamp/haystack#8704 — the server must accept any port for the CLI's loopback client. Deploy the server first; it stays compatible with the fixed port, so this can merge and ship in the next CLI release once that's live. A CLI built from this branch against a server without it gets
redirect_uri mismatch.Tests
TestLoginOAuthFlow: assertsLoginlistens ontcp127.0.0.1:0, that the listener is bound to a real127.0.0.1port, and that the samehttp://127.0.0.1:<port>/callbackappears in the authorization URL and in the token exchange.TestLoginListenFailure: a failed bind surfaces asfailed to start callback serverbefore any callback wait runs.TestWaitForCallback*and the logger test now hand the listener in directly.go test -race ./...green forinternal/auth;golangci-lintclean. (internal/tui'sopen_remote_unix_testfails on this macOS sandbox onmaintoo — unix socket path length — unrelated.)AGENTS.md updated to stop naming the fixed port.
Summary by cubic
Binds the OAuth callback listener for
hey auth loginto an ephemeral loopback port (127.0.0.1:0) instead of the fixed127.0.0.1:8976, so a local process can no longer squat the port and block sign-in. Theredirect_urinow carries whichever port the kernel assigned, in both the authorization request and the token exchange.Rollout
redirect_uri; deploy the server first — it stays compatible with the fixed port until this ships.redirect_uri mismatch.Written for commit f3deedc. Summary will update on new commits.