diff --git a/pkg/slack/client.go b/pkg/slack/client.go index 4ea1714b6..400fbaab2 100644 --- a/pkg/slack/client.go +++ b/pkg/slack/client.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "net/http" + "net/url" "go.gearno.de/kit/httpclient" "go.gearno.de/kit/log" @@ -30,6 +31,7 @@ const ( slackAPIPostMessage = "https://slack.com/api/chat.postMessage" slackAPIUpdateMessage = "https://slack.com/api/chat.update" slackAPIConversationJoin = "https://slack.com/api/conversations.join" + slackWebhookHost = "hooks.slack.com" ) type ( @@ -104,6 +106,10 @@ func (c *Client) CreateMessage(ctx context.Context, accessToken string, channelI } func (c *Client) UpdateInteractiveMessage(ctx context.Context, responseURL string, body map[string]any) error { + if err := validateSlackResponseURL(responseURL); err != nil { + return fmt.Errorf("invalid Slack response URL: %w", err) + } + updatePayload := map[string]any{ "replace_original": true, "text": body["text"], @@ -257,3 +263,20 @@ func (c *Client) JoinChannel(ctx context.Context, accessToken string, channelID return nil } + +func validateSlackResponseURL(responseURL string) error { + parsedURL, err := url.Parse(responseURL) + if err != nil { + return fmt.Errorf("invalid URL format: %w", err) + } + + if parsedURL.Scheme != "https" { + return fmt.Errorf("invalid URL scheme: must be https") + } + + if parsedURL.Host != slackWebhookHost { + return fmt.Errorf("invalid URL host: must be %s", slackWebhookHost) + } + + return nil +} diff --git a/pkg/trust/slack_message_service.go b/pkg/trust/slack_message_service.go index 9f2e61043..f5d324881 100644 --- a/pkg/trust/slack_message_service.go +++ b/pkg/trust/slack_message_service.go @@ -30,7 +30,6 @@ import ( const ( slackMessageDeduplicationWindow = 7 * 24 * time.Hour - trustCenterAccessURLFormat = "https://%s/organizations/%s/trust-center/access" ) type (