hasUsableBaseURL reports whether s.baseURL is a URL a verification-email recipient on the public internet can actually reach. It supersets the unreachable-host warning in SetBaseURL (BUG-899): the bind-all hosts 0.0.0.0 / :: are the right thing to bind() to but the wrong thing to email, and so is ev
()
| 554 | // than minting a write-locked user). Self-host and admin/invitation signup are |
| 555 | // unaffected either way. |
| 556 | func (s *Server) hasUsableBaseURL() bool { |
| 557 | if s.baseURL == "" { |
| 558 | return false |
| 559 | } |
| 560 | u, err := url.Parse(s.baseURL) |
| 561 | if err != nil { |
| 562 | return false |
| 563 | } |
| 564 | if u.Scheme != "http" && u.Scheme != "https" { |
| 565 | return false |
| 566 | } |
| 567 | // The verification link is built by concatenation (baseURL + |
| 568 | // "/verify-email/" + token), so a base URL carrying a query or fragment |
| 569 | // would push the route into the query/fragment and break the link. |
| 570 | if u.RawQuery != "" || u.Fragment != "" { |
| 571 | return false |
| 572 | } |
| 573 | host := u.Hostname() |
| 574 | if host == "" { |
| 575 | return false |
| 576 | } |
| 577 | // A present port must be a valid TCP port (1–65535); url.Parse accepts |
| 578 | // out-of-range numeric ports that no client can actually connect to. |
| 579 | if p := u.Port(); p != "" { |
| 580 | n, perr := strconv.Atoi(p) |
| 581 | if perr != nil || n < 1 || n > 65535 { |
| 582 | return false |
| 583 | } |
| 584 | } |
| 585 | |
| 586 | // Reject literal IPs outright — a usable public verification endpoint is a |
| 587 | // DNS hostname, and "is this IP publicly reachable" is not decidable from a |
| 588 | // finite denylist. Fail closed on any IP. |
| 589 | if _, aerr := netip.ParseAddr(host); aerr == nil { |
| 590 | return false |
| 591 | } |
| 592 | |
| 593 | // The host must be a syntactically-valid, multi-label public FQDN (rejects |
| 594 | // malformed hosts like ".com", "foo..com", "-a.com" and special-use TLDs). |
| 595 | return isPublicDNSName(host) |
| 596 | } |
| 597 | |
| 598 | // isPublicDNSName reports whether host is a syntactically-valid public FQDN |
| 599 | // (RFC 1123 labels) whose TLD is neither a special-use reserved name nor |
no test coverage detected