fix(tipping): validate NWC URI before saving; add HTTP timeouts on LNURL - #63
Open
oth-body wants to merge 1 commit into
Open
fix(tipping): validate NWC URI before saving; add HTTP timeouts on LNURL#63oth-body wants to merge 1 commit into
oth-body wants to merge 1 commit into
Conversation
Two defense-in-depth fixes on the tipping path (hoot -tip, hoot -nwc):
1. validateNWCURI runs before saveNWCURI writes to disk.
Pre-fix: `hoot -nwc garbage` silently wrote "garbage" to nwc.txt
(mode 0600, but the secret was the only auth — if the file was
ever copied to a filesystem that strips perms, the connection
string leaked). Post-fix: structural check rejects empty / wrong-
scheme / missing-required-fields URIs immediately with an actionable
error message before any disk write.
The existing TestNWCParsing pinned the bug ("invalid-uri" was the
test input; "saved successfully" was the assertion). Updated to
use a properly-formatted URI and assert save still works.
2. resolveLud16 and fetchLightningInvoice used the global http.Get
with no timeout. If the LNURL endpoint hangs (slow wallet,
network partition, malicious response that never closes the
stream), `hoot -tip` would freeze forever waiting for the
response. Now: explicit http.Client{Timeout: 10*time.Second} for
both. LUD-16 spec recommends 10s for lnurlp responses.
Tests: nwc_validation_test.go (7 table-driven cases) covers
empty/wrong-scheme/missing-fields/valid-with-extras/valid-basic.
Replaces the bug-pinning assertion in hoot_test.go with a behavior-
correct one.
No conflict with #61 (silent-failures-hoot) or #62 (publish-error-
surfacing). All three branches touch hoot.go but at disjoint
functions: #61 = defaultRelays/generateProfileID/payInvoiceNWC,
#62 = main() publish loop + publishNote(), this PR = NWC helpers +
HTTP clients in resolveLud16/fetchLightningInvoice.
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
Two defense-in-depth fixes on the Lightning tipping path (
hoot -nwc,hoot -tip).What this fixes
1. NWC URI was saved to disk without validation
Pre-fix:
hoot -nwc garbagesilently wrote"garbage"tonwc.txt(mode 0600, but the connection secret was the only auth — if the file ever leaked to a filesystem that strips permissions, the connection was wide open). The user got no error and no indication that the URI was malformed.Post-fix: a new
validateNWCURI(uri)helper runs before any disk write. It rejects:nostr+walletconnect://)?relay=query parameter?secret=query parameterThe check is intentionally permissive — any future NIP-47 extension field passes through unchanged — but it catches the cases that would have failed later in a less-actionable way.
2.
resolveLud16andfetchLightningInvoicehad no HTTP timeoutPre-fix: both used the default
http.Getwith no context and no timeout. If the LNURL endpoint hangs (slow wallet, network partition, malicious response that never closes the stream),hoot -tipwould freeze forever waiting for the response. This is the kind of failure that turns a one-shot CLI invocation into a manual kill.Post-fix: explicit
http.Client{Timeout: 10*time.Second}for both calls. The LUD-16 spec recommends a 10s timeout for lnurlp responses, and 10s is short enough to not annoy users on slow networks but long enough to not abort legitimate slow responses.Tests
nwc_validation_test.go(new, 7 table-driven cases):""https://example.comnostr+walletconnect://?relay=wss://r&secret=abcnostr+walletconnect://pubkey?secret=abcnostr+walletconnect://pubkey?relay=wss://rnostr+walletconnect://pubkey123?relay=wss://...&secret=hexsecretAlso updated
hoot_test.goTestNWCParsing— the old version pinned the bug (passed"invalid-uri"and expected "saved successfully"). New version uses a properly-formatted URI and asserts the save path still works end-to-end.Conflict check
defaultRelays,generateProfileID,payInvoiceNWC. This PR modifies the NWC helpers andresolveLud16/fetchLightningInvoice.publishNote()and rewired themain()publish loop. This PR touches the tipping path.