From 9abc39fe97a6b1e73d73b6a4a20cc75c4f57aae2 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 1 Jul 2026 07:12:17 +0000 Subject: [PATCH] fix #2391 Validate incoming batch tags --- irc/handlers.go | 11 +++++++++-- irc/utils/args.go | 13 +++++++++++++ irc/utils/args_test.go | 12 ++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/irc/handlers.go b/irc/handlers.go index e64d788c..d83dc37b 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -548,7 +548,8 @@ func dispatchAwayNotify(client *Client, awayMessage string) { // BATCH {+,-}reference-tag type [params...] func batchHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool { tag := msg.Params[0] - if len(tag) != 0 { + tagValid := len(tag) != 0 && utils.IsValidBatchTag(tag[1:]) + if tagValid { switch tag[0] { case '+': // can't open a new C2S batch with one already open, even of a different type @@ -570,7 +571,13 @@ func batchHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respon } } } - failBatch(server, rb) + // failure cases + if tagValid { + // generic failure with INVALID_PARAMS + failBatch(server, rb) + } else { + rb.Add(nil, server.name, "FAIL", "BATCH", "INVALID_REFTAG", utils.SafeErrorParam(tag), "Provided batch reference tag contains disallowed characters") + } // reset any local state rb.session.EndMultilineBatch("") rb.session.tokenValidateBatch = nil diff --git a/irc/utils/args.go b/irc/utils/args.go index a80bbab5..6d07ef38 100644 --- a/irc/utils/args.go +++ b/irc/utils/args.go @@ -6,6 +6,7 @@ package utils import ( "errors" "fmt" + "regexp" "strings" "time" ) @@ -16,6 +17,14 @@ const ( var ( ErrInvalidParams = errors.New("Invalid parameters") + + /* + batch specification says: + The reference tag MUST be treated as an opaque identifier. + Reference tag MUST contain only ASCII letters, numbers, and/or hyphen, + and MUST be case-sensitive. + */ + batchTagRegexp = regexp.MustCompile(`^[A-Za-z0-9-]+$`) ) func StringToBool(str string) (result bool, err error) { @@ -58,3 +67,7 @@ func BoolDefaultTrue(value *bool) bool { } return true } + +func IsValidBatchTag(tag string) bool { + return batchTagRegexp.MatchString(tag) +} diff --git a/irc/utils/args_test.go b/irc/utils/args_test.go index 5c84b26a..1839aa72 100644 --- a/irc/utils/args_test.go +++ b/irc/utils/args_test.go @@ -30,3 +30,15 @@ func TestSafeErrorParam(t *testing.T) { assertEqual(SafeErrorParam("#hi:there"), "#hi:there", t) assertEqual(SafeErrorParam(""), "*", t) } + +func TestIsValidBatchTag(t *testing.T) { + assertEqual(IsValidBatchTag("-"), true, t) + assertEqual(IsValidBatchTag("1"), true, t) + assertEqual(IsValidBatchTag("x"), true, t) + assertEqual(IsValidBatchTag("9P5fxSwIXviY1YHHuejhaQ"), true, t) + assertEqual(IsValidBatchTag("0123456789-abcdef"), true, t) + + assertEqual(IsValidBatchTag(""), false, t) + assertEqual(IsValidBatchTag("_"), false, t) + assertEqual(IsValidBatchTag("qt-KrJ5H6bNsaLr_mDE4QQ"), false, t) +}