From bb06b905436326dca4887e00353f173a0b54ad4c Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 5 Jun 2026 14:29:43 +0000 Subject: [PATCH] types: skip malformed derp.urls entries instead of panicking A failed url.Parse left a nil pointer that was dereferenced at startup. --- hscontrol/types/config.go | 8 +++++--- hscontrol/types/derp_config_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 hscontrol/types/derp_config_test.go diff --git a/hscontrol/types/config.go b/hscontrol/types/config.go index a2cace06..6a6d59dc 100644 --- a/hscontrol/types/config.go +++ b/hscontrol/types/config.go @@ -712,8 +712,8 @@ func derpConfig() DERPConfig { urlStrs := viper.GetStringSlice("derp.urls") - urls := make([]url.URL, len(urlStrs)) - for index, urlStr := range urlStrs { + urls := make([]url.URL, 0, len(urlStrs)) + for _, urlStr := range urlStrs { urlAddr, err := url.Parse(urlStr) if err != nil { log.Error(). @@ -721,9 +721,11 @@ func derpConfig() DERPConfig { Str("url", urlStr). Err(err). Msg("Failed to parse url, ignoring...") + + continue } - urls[index] = *urlAddr + urls = append(urls, *urlAddr) } paths := viper.GetStringSlice("derp.paths") diff --git a/hscontrol/types/derp_config_test.go b/hscontrol/types/derp_config_test.go new file mode 100644 index 00000000..ffff3ed2 --- /dev/null +++ b/hscontrol/types/derp_config_test.go @@ -0,0 +1,28 @@ +package types + +import ( + "testing" + + "github.com/spf13/viper" +) + +// TestDerpConfigSkipsMalformedURL ensures a malformed derp.urls entry is +// skipped (as the "ignoring..." log promises) rather than dereferencing the +// nil *url.URL that url.Parse returns on error, which crashed the server at +// startup. +func TestDerpConfigSkipsMalformedURL(t *testing.T) { + viper.Reset() + defer viper.Reset() + + viper.Set("derp.urls", []string{ + "https://controlplane.tailscale.com/derpmap/default", + "://bad", + }) + + cfg := derpConfig() + + if len(cfg.URLs) != 1 { + t.Fatalf("expected the malformed derp.urls entry to be skipped, got %d urls: %v", + len(cfg.URLs), cfg.URLs) + } +}