From e5c7772d3c7cf07096b5c9f21a73d1573f3672ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E6=99=BA=E8=B6=850668000959?= Date: Fri, 5 Jun 2026 09:49:44 +0800 Subject: [PATCH 1/2] fix(channels): add ok checks for type assertions in toChannelHashes Two type assertions in toChannelHashes could panic when channel config values had unexpected types from JSON unmarshal: 1) value[enabled].(bool) panics if the key is missing or not a bool 2) vv.(map[string]string) panics when JSON unmarshal produces map[string]any. Add ok checks to safely handle both cases. --- pkg/channels/manager_channel.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/channels/manager_channel.go b/pkg/channels/manager_channel.go index 9dbd35cab..b6b407c59 100644 --- a/pkg/channels/manager_channel.go +++ b/pkg/channels/manager_channel.go @@ -17,7 +17,7 @@ func toChannelHashes(cfg *config.Config) map[string]string { _ = json.Unmarshal(marshal, &channelConfig) for key, value := range channelConfig { - if !value["enabled"].(bool) { + if enabled, ok := value["enabled"].(bool); !ok || !enabled { continue } hiddenValues(key, value, ch.Get(key)) @@ -94,7 +94,15 @@ func hiddenValues(key string, value map[string]any, ch *config.Channel) { vv := value["webhooks"] webhooks := make(map[string]string) if vv != nil { - webhooks = vv.(map[string]string) + if m, ok := vv.(map[string]string); ok { + webhooks = m + } else if m, ok := vv.(map[string]any); ok { + for k, w := range m { + if s, ok := w.(string); ok { + webhooks[k] = s + } + } + } } if settings, ok := v.(*config.TeamsWebhookSettings); ok { for name, target := range settings.Webhooks { From 9f246a64827eb90d1ef2b6001c00eaad4b2a886f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E6=99=BA=E8=B6=850668000959?= Date: Sat, 6 Jun 2026 00:31:44 +0800 Subject: [PATCH 2/2] test(channels): add edge case tests for toChannelHashes type assertions Add 3 tests covering scenarios that previously panicked: 1) missing enabled key in settings 2) enabled field with non-bool type 3) teams_webhook with webhooks using map[string]any from JSON unmarshal --- pkg/channels/manager_channel_test.go | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/pkg/channels/manager_channel_test.go b/pkg/channels/manager_channel_test.go index b991e58d6..9d0373299 100644 --- a/pkg/channels/manager_channel_test.go +++ b/pkg/channels/manager_channel_test.go @@ -151,3 +151,57 @@ func TestToChannelHashes_RealWorldChannel(t *testing.T) { assert.Equal(t, 1, len(h)) assert.Contains(t, h, "telegram") } + +func TestToChannelHashes_MissingEnabledKey(t *testing.T) { + cfg := config.DefaultConfig() + cfg.Channels["test"] = &config.Channel{ + Settings: config.RawNode(`{"key":"value"}`), + } + + // Should not panic — the ok check safely handles the missing/false case + assert.NotPanics(t, func() { + _ = toChannelHashes(cfg) + }) + h := toChannelHashes(cfg) + assert.Equal(t, 0, len(h), "channel with Enabled=false (default) skipped") +} + +func TestToChannelHashes_EnabledNotBool(t *testing.T) { + cfg := config.DefaultConfig() + cfg.Channels["test"] = &config.Channel{ + Enabled: false, + Settings: config.RawNode(`{"enabled":"yes","boolField":true}`), + } + + // Should not panic — string "enabled" won't match bool assertion, ok=false + assert.NotPanics(t, func() { + _ = toChannelHashes(cfg) + }) + h := toChannelHashes(cfg) + assert.Equal(t, 0, len(h), "string enabled not treated as true") +} + +func TestToChannelHashes_TeamsWebhookWithWebhooks(t *testing.T) { + cfg := config.DefaultConfig() + // teams_webhook with configured webhooks — this is the real-world + // scenario where the map type from JSON unmarshal (map[string]any) + // would cause a panic on the old unchecked vv.(map[string]string) + settings, _ := json.Marshal(map[string]any{ + "enabled": true, + "webhooks": map[string]any{ + "hook1": "https://example.com/webhook", + }, + }) + cfg.Channels["teams_webhook"] = &config.Channel{ + Enabled: true, + Type: config.ChannelTeamsWebHook, + Settings: config.RawNode(settings), + } + + assert.NotPanics(t, func() { + _ = toChannelHashes(cfg) + }) + h := toChannelHashes(cfg) + assert.Equal(t, 1, len(h)) + assert.Contains(t, h, "teams_webhook") +}