fix(nip46): refuse to dial relays through inherited *_PROXY env vars - #73
Merged
Merged
Conversation
Hoot's NIP-46 sign-in flow uses github.com/nbd-wtf/go-nostr's
nostr.RelayConnect, which delegates to net/http and therefore
honors HTTPS_PROXY / HTTP_PROXY / ALL_PROXY / SOCKS_PROXY env
vars inherited from the parent shell. If the user runs hoot
inside torsocks, a launcher that exports HTTPS_PROXY, or a shell
that already has Tor configured for monerod / curl, the wss://
dials to relay.damus.io / relay.nostr.band / nostr.wine (or
whatever the user picked) get routed through 127.0.0.1:9050.
When nothing is listening there — which is the typical case on
a workstation without an active Tor — every dial fails with
'dial tcp 127.0.0.1:9050: connect: connection refused', which
bubbles up as 'failed to connect to port 9050' in the TUI and
gives the user no actionable signal.
Fix it two ways:
- nip46.ConnectRelays now refuses to dial at all when any
*_PROXY env var is set, returning a clear error that names
the offending env var and the proxy host:port. The user can
either unset it (or run hoot outside torsocks). This matches
what every other Nostr TUI does — nak, lume, etc. — none
of them proxy wss:// connections by default.
- Up-front validation of every configured relay URL (rejecting
blanks and non-ws:// / non-wss:// schemes) so a misconfigured
relays.txt surfaces a clear error instead of a confusing
websocket one.
Anchored against master after PR #69 / #70 / #72 restructured
the NIP-46 dial path (RelayURL string -> RelayURLs []string,
WaitForConnection -> ConnectRelays + CheckConnection). Tests
updated accordingly: ConnectRelays is the new dial entry point,
and validateRelayURLs is exercised with single-bad-URL and
mixed-good-and-bad inputs.
Tests in nip46/nip46_test.go pin:
- the proxy env var detection order (HTTPS_PROXY beats
HTTP_PROXY beats ALL_PROXY; socks fallbacks come last)
- that malformed or empty proxy values fall through to the
next valid var (matching Go's stdlib httpproxy behaviour)
- that ConnectRelays surfaces the env var name and port on
the user-visible error path (this is the bug's regression
guard)
- that blank and non-wss relay URLs are rejected up front
instead of producing a confusing websocket error later
- that Session.Close is idempotent when no dial was attempted
oth-body
force-pushed
the
fix/nip46-signin-proxy
branch
from
September 15, 2026 16:38
1e11022 to
97585df
Compare
Owner
Author
|
Rebased onto master (was |
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.
Summary
When users try to sign in via Amber, hoot's NIP-46 flow calls
nostr.RelayConnect(ctx, relayURL)to subscribe for the bunker's response. That function delegates tonet/http, which honors theHTTPS_PROXY/HTTP_PROXY/ALL_PROXY/SOCKS_PROXYenv vars inherited from the parent shell. If any of those point at a proxy port that isn't running (typically127.0.0.1:9050on machines without Tor), the dial fails withconnect: connection refused, and the TUI shows the user a "failed to connect to port 9050" error with no signal about the actual cause.This is the dominant "Amber sign-in failed" complaint in practice. It happens when:
torsocks(TUI tools don't need it)HTTPS_PROXYforcurl/monerod/nixand they don't realise hoot inherits itHTTPS_PROXYfor outgoing HTTPS and forgot to scope itFix
nip46.WaitForConnectionnow:*_PROXYenv var is set, returning a user-actionable error that names the offending env var and the proxy host:port. Matches what every other Nostr TUI does (nak,lume, etc.) — none of them proxywss://by default.Tests
nip46/nip46_test.gopins:httpproxy(HTTPS_PROXY > HTTP_PROXY > ALL_PROXY > socks fallbacks)WaitForConnectionsurfaces the env var name and port on the user-visible error path (regression guard)Session.Closeis idempotent when no dial was attempted11 tests, all pass.
Tested manually
Followups
For the root-cause fix (so users who want Tor can route through it explicitly without
*_PROXY), I'd like to file a separate PR againstgithub.com/nbd-wtf/go-nostradding aWithProxyURLRelayOption. The defaulthttpproxy-driven behaviour is the wrong default for a TUI app — every other Nostr client in the wild ships without it.