Derive the source detail BaseURL scheme from reqtls (closes #272) #286
Reference in New Issue
Block a user
Delete Branch "issue-272-baseurl-scheme"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #272.
renderSourceDetailassigned the rawX-Forwarded-Protovalue into the URL scheme. The scheme now comes fromreqtls.IsTLS(r)— the shared predicate, consumed, not reimplemented — so it is only everhttporhttps, and all three TLS-decision sites agree. This also fixes the inverted precedence: a present header no longer overwrites what a direct TLS connection proved.The host: left as the request sent it, deliberately
r.Hoststays unconstrained.Hostheader carrieshost:portthere) and an IPv6 literal. Both are covered by a test, and the live run below is on a non-default port.NoCachemiddleware marksno-store; it is never stored.templates/source_detail.html:73putsBaseURLin HTML text inside<code>, sohtml/template'surlFilternever runs, andstatic/js/app.jscopies it withtextContent.That last point is contextual, not intrinsic, so a comment at the assignment site marks the trap for anyone later moving
BaseURLinto anhref.A garbage token renders
http://host: anything that is nothttpsis not TLS, per the shared predicate. The operator sees a URL that is visibly the wrong scheme rather than one that is malformed.Verification
make checkgreen withGOFLAGS=-count=1after the rebase onto currentnext— tests ran uncached (ok sneak.berlin/go/webhooker/internal/handlers 20.774s, no(cached)lines), lint ran in Docker,0 issues.The new test drives the real handler and extracts the rendered entrypoint URL from the page, so it asserts what the operator actually copies. It was written first and failed on unmodified
nextfor every spelling below.Live instance on a non-default port,
Host: hooks.example.com:19520, before and after:X-Forwarded-Protohttp://hooks.example.com:19520/webhook/...httpshttps://...HTTPSHTTPS://hooks.example.com:19520/webhook/...https://...https, httphttps, http://hooks.example.com:19520/webhook/...https://...httphttp://...javascript:alert(1)//javascript:alert(1)//://hooks.example.com:19520/webhook/...http://...Unit coverage adds
https,https,https(trailing space), direct TLS outranking a header claiminghttp, and the host authority surviving verbatim forhooks.example.com:8443,[2001:db8::1]:8443and a bare hostname.Scope:
internal/handlersonly.internal/reqtlsis consumed unchanged.PASS. Independently reproduced on unmodified
nextand confirmed fixed: my own 23-case probe on the rendered page (all issue spellings plusHtTpS, leading space,HTTP,ftp,data:text/html,x,https://evil, a 64-char token, TLS+garbage, IPv6 without a port) yields 17 out-of-range schemes onnext— includingjavascript:alert(1)//://host— and 0 on3939cd8, with the authority preserved verbatim forhost:portand[2001:db8::1].reqtlsconsumed unchanged, no second parse anywhere, direct TLS now outranks a header claiminghttp. Trap comment accurate:BaseURLhas exactly one render site,source_detail.html:73, still HTML text inside<code>. The author's tests fail onnextand pass on head.make checkgreen from a clean clone withGOFLAGS=-count=1in 73s, 0(cached)markers, lint in Docker at0 issues; CI green on the head commit; fast-forwardable ontonext.Host decision: the argument holds. Traced every escape path — no redirect builds a
Locationfromr.Host, noHeader.Get("Host")anywhere, no mail path, the delivery engine rejects aHostoverride, andnet/httppromotesHostout ofr.Header(verified) so the receiver'sjson.Marshal(r.Header)cannot persist it. The value round-trips only to the authenticated requester who supplied it, on aNoCacheroute. The one pre-existing outbound use isinternal/server/sentry.go:175, which is deliberate, documented, and unrelated to this change.Non-blocking nit:
source_detail_baseurl_test.go:117assertsrequire.Len(t, match, 2, "the page must render exactly one entrypoint URL"), butFindStringSubmatchreturns only the first match, so this proves at-least-one, not exactly-one. Harmless — the fixture seeds a single entrypoint — but the message overclaims.Disclosure: the probe and the
next-side runs were done in a throwaway copy of the tree, wherego testwas invoked directly; the reviewed tree itself saw onlymaketargets.