diff --git a/irc/chanserv.go b/irc/chanserv.go index 361f394a..c4b75974 100644 --- a/irc/chanserv.go +++ b/irc/chanserv.go @@ -213,8 +213,17 @@ func csAmodeHandler(service *ircService, server *Server, client *Client, command } modeChanges, unknown := modes.ParseChannelModeChanges(params[1:]...) + invalid := len(unknown) != 0 + // #2002: +f takes an argument but is not a channel-user mode, + // check for anything valid as a channel mode change that is not valid + // as an AMODE change + for _, modeChange := range modeChanges { + if !utils.SliceContains(modes.ChannelUserModes, modeChange.Mode) { + invalid = true + } + } var change modes.ModeChange - if len(modeChanges) > 1 || len(unknown) > 0 { + if len(modeChanges) > 1 || invalid { service.Notice(rb, client.t("Invalid mode change")) return } else if len(modeChanges) == 1 { diff --git a/irc/utils/types.go b/irc/utils/types.go index 5ad2ce93..ca1e4f7a 100644 --- a/irc/utils/types.go +++ b/irc/utils/types.go @@ -34,3 +34,12 @@ func ReverseSlice[T any](results []T) { results[i], results[j] = results[j], results[i] } } + +func SliceContains[T comparable](slice []T, elem T) (result bool) { + for _, t := range slice { + if elem == t { + return true + } + } + return false +}