diff --git a/SPECS/keda/CVE-2026-41889.patch b/SPECS/keda/CVE-2026-41889.patch new file mode 100644 index 00000000000..cfecf9c20d0 --- /dev/null +++ b/SPECS/keda/CVE-2026-41889.patch @@ -0,0 +1,160 @@ +From 9ab2b0db744e8c0d0b5e315652ae0adfad671719 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Mon, 11 May 2026 10:25:57 +0000 +Subject: [PATCH] Fix SQL sanitizer to handle PostgreSQL dollar-quoted strings + and clamp placeholder overflow; add supporting lexer logic + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/jackc/pgx/commit/60644f84918a8af66d14a4b0d865d4edafd955da.patch +--- + .../pgx/v5/internal/sanitize/sanitize.go | 99 +++++++++++++++++-- + 1 file changed, 91 insertions(+), 8 deletions(-) + +diff --git a/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go b/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go +index df58c448..3c9053cf 100644 +--- a/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go ++++ b/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go +@@ -4,6 +4,7 @@ import ( + "bytes" + "encoding/hex" + "fmt" ++ "math" + "strconv" + "strings" + "time" +@@ -105,12 +106,13 @@ func QuoteBytes(buf []byte) string { + } + + type sqlLexer struct { +- src string +- start int +- pos int +- nested int // multiline comment nesting level. +- stateFn stateFn +- parts []Part ++ src string ++ start int ++ pos int ++ nested int // multiline comment nesting level. ++ dollarTag string // active tag while inside a dollar-quoted string (may be empty for $$). ++ stateFn stateFn ++ parts []Part + } + + type stateFn func(*sqlLexer) stateFn +@@ -140,6 +142,15 @@ func rawState(l *sqlLexer) stateFn { + l.start = l.pos + return placeholderState + } ++ // PostgreSQL dollar-quoted string: $[tag]$...$[tag]$. The $ was ++ // just consumed; try to match the rest of the opening tag. ++ // Without this, placeholders embedded inside dollar-quoted ++ // literals would be incorrectly substituted. ++ if tagLen, ok := scanDollarQuoteTag(l.src[l.pos:]); ok { ++ l.dollarTag = l.src[l.pos : l.pos+tagLen] ++ l.pos += tagLen + 1 // advance past tag and closing '$' ++ return dollarQuoteState ++ } + case '-': + nextRune, width := utf8.DecodeRuneInString(l.src[l.pos:]) + if nextRune == '-' { +@@ -207,6 +218,7 @@ func doubleQuoteState(l *sqlLexer) stateFn { + l.start = l.pos + } + return nil ++ + } + } + } +@@ -222,8 +234,16 @@ func placeholderState(l *sqlLexer) stateFn { + l.pos += width + + if '0' <= r && r <= '9' { +- num *= 10 +- num += int(r - '0') ++ // Clamp rather than silently wrap on pathological input like ++ // "$92233720368547758070" which would otherwise overflow int and ++ // could land on a valid args index. Any value above MaxInt32 far ++ // exceeds any plausible args length, so Sanitize will correctly ++ // return "insufficient arguments". ++ if num > (math.MaxInt32-9)/10 { ++ num = math.MaxInt32 ++ } else { ++ num = num*10 + int(r-'0') ++ } + } else { + l.parts = append(l.parts, num) + l.pos -= width +@@ -233,6 +253,69 @@ func placeholderState(l *sqlLexer) stateFn { + } + } + ++// dollarQuoteState consumes the body of a PostgreSQL dollar-quoted string ++// ($[tag]$...$[tag]$). The opening tag (including its terminating '$') has ++// already been consumed. ++func dollarQuoteState(l *sqlLexer) stateFn { ++ closer := "$" + l.dollarTag + "$" ++ idx := strings.Index(l.src[l.pos:], closer) ++ if idx < 0 { ++ // Unterminated — mirror the behavior of other quoted-string states by ++ // consuming the remaining input into the current part and stopping. ++ if len(l.src)-l.start > 0 { ++ l.parts = append(l.parts, l.src[l.start:]) ++ l.start = len(l.src) ++ } ++ l.pos = len(l.src) ++ return nil ++ } ++ l.pos += idx + len(closer) ++ l.dollarTag = "" ++ return rawState ++} ++ ++// scanDollarQuoteTag checks whether src begins with an optional dollar-quoted ++// string tag followed by a closing '$'. src must point just past the opening ++// '$'. Returns the byte length of the tag (zero for an anonymous $$) and ++// whether a valid tag was found. ++// ++// Tag grammar matches the PostgreSQL lexer (scan.l): ++// ++// dolq_start: [A-Za-z_\x80-\xff] ++// dolq_cont: [A-Za-z0-9_\x80-\xff] ++func scanDollarQuoteTag(src string) (int, bool) { ++ first := true ++ for i := 0; i < len(src); { ++ r, w := utf8.DecodeRuneInString(src[i:]) ++ if r == '$' { ++ return i, true ++ } ++ if !isDollarTagRune(r, first) { ++ return 0, false ++ } ++ first = false ++ i += w ++ } ++ return 0, false ++} ++ ++func isDollarTagRune(r rune, first bool) bool { ++ switch { ++ case r == '_': ++ return true ++ case 'a' <= r && r <= 'z': ++ return true ++ case 'A' <= r && r <= 'Z': ++ return true ++ case !first && '0' <= r && r <= '9': ++ return true ++ case r >= 0x80 && r != utf8.RuneError: ++ return true ++ } ++ return false ++} ++ ++ + func escapeStringState(l *sqlLexer) stateFn { + for { + r, width := utf8.DecodeRuneInString(l.src[l.pos:]) +-- +2.45.4 + diff --git a/SPECS/keda/keda.spec b/SPECS/keda/keda.spec index 0bff16ffd0f..31468596361 100644 --- a/SPECS/keda/keda.spec +++ b/SPECS/keda/keda.spec @@ -1,7 +1,7 @@ Summary: Kubernetes-based Event Driven Autoscaling Name: keda Version: 2.14.1 -Release: 12%{?dist} +Release: 13%{?dist} License: ASL 2.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -39,6 +39,7 @@ Patch13: CVE-2025-47911.patch Patch14: CVE-2025-58190.patch Patch15: CVE-2026-2303.patch Patch16: CVE-2026-35469.patch +Patch17: CVE-2026-41889.patch BuildRequires: golang >= 1.15 @@ -75,6 +76,9 @@ cp ./bin/keda-admission-webhooks %{buildroot}%{_bindir} %{_bindir}/%{name}-admission-webhooks %changelog +* Mon May 11 2026 Azure Linux Security Servicing Account - 2.14.1-13 +- Patch for CVE-2026-41889 + * Thu May 07 2026 Akhila Guruju - 2.14.1-12 - Patch CVE-2026-34569