Skip to content

Commit 290ea6e

Browse files
azurelinux-securityKanishk BansalKanishk-Bansaljykanase
authored
[AutoPR- Security] Patch application-gateway-kubernetes-ingress for CVE-2025-30204, CVE-2025-47911 [MEDIUM] (#15886)
Signed-off-by: Kanishk Bansal <kanbansal@microsoft.com> Co-authored-by: Kanishk Bansal <kanbansal@microsoft.com> Co-authored-by: Kanishk Bansal <103916909+Kanishk-Bansal@users.noreply.github.com> Co-authored-by: jykanase <v-jykanase@microsoft.com>
1 parent 5de4ce3 commit 290ea6e

File tree

3 files changed

+276
-2
lines changed

3 files changed

+276
-2
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
From 6a4015ba092822e5b0c92c68552ff613c419bd43 Mon Sep 17 00:00:00 2001
2+
From: Michael Fridman <mfridman@buf.build>
3+
Date: Fri, 21 Mar 2025 16:42:51 -0400
4+
Subject: [PATCH] Backporting 0951d18 to v4
5+
6+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
7+
Upstream-reference: https://github.com/golang-jwt/jwt/commit/2f0e9add62078527821828c76865661aa7718a84.patch
8+
---
9+
vendor/github.com/dgrijalva/jwt-go/jwt_test.go | 89 ++++++++++++++++++++
10+
vendor/github.com/dgrijalva/jwt-go/parser.go | 36 +++++++-
11+
2 files changed, 122 insertions(+), 3 deletions(-)
12+
create mode 100644 vendor/github.com/dgrijalva/jwt-go/jwt_test.go
13+
14+
diff --git a/vendor/github.com/dgrijalva/jwt-go/jwt_test.go b/vendor/github.com/dgrijalva/jwt-go/jwt_test.go
15+
new file mode 100644
16+
index 0000000..b01e899
17+
--- /dev/null
18+
+++ b/vendor/github.com/dgrijalva/jwt-go/jwt_test.go
19+
@@ -0,0 +1,89 @@
20+
+package jwt
21+
+
22+
+import (
23+
+ "testing"
24+
+)
25+
+
26+
+func TestSplitToken(t *testing.T) {
27+
+ t.Parallel()
28+
+
29+
+ tests := []struct {
30+
+ name string
31+
+ input string
32+
+ expected []string
33+
+ isValid bool
34+
+ }{
35+
+ {
36+
+ name: "valid token with three parts",
37+
+ input: "header.claims.signature",
38+
+ expected: []string{"header", "claims", "signature"},
39+
+ isValid: true,
40+
+ },
41+
+ {
42+
+ name: "invalid token with two parts only",
43+
+ input: "header.claims",
44+
+ expected: nil,
45+
+ isValid: false,
46+
+ },
47+
+ {
48+
+ name: "invalid token with one part only",
49+
+ input: "header",
50+
+ expected: nil,
51+
+ isValid: false,
52+
+ },
53+
+ {
54+
+ name: "invalid token with extra delimiter",
55+
+ input: "header.claims.signature.extra",
56+
+ expected: nil,
57+
+ isValid: false,
58+
+ },
59+
+ {
60+
+ name: "invalid empty token",
61+
+ input: "",
62+
+ expected: nil,
63+
+ isValid: false,
64+
+ },
65+
+ {
66+
+ name: "valid token with empty parts",
67+
+ input: "..signature",
68+
+ expected: []string{"", "", "signature"},
69+
+ isValid: true,
70+
+ },
71+
+ {
72+
+ // We are just splitting the token into parts, so we don't care about the actual values.
73+
+ // It is up to the caller to validate the parts.
74+
+ name: "valid token with all parts empty",
75+
+ input: "..",
76+
+ expected: []string{"", "", ""},
77+
+ isValid: true,
78+
+ },
79+
+ {
80+
+ name: "invalid token with just delimiters and extra part",
81+
+ input: "...",
82+
+ expected: nil,
83+
+ isValid: false,
84+
+ },
85+
+ {
86+
+ name: "invalid token with many delimiters",
87+
+ input: "header.claims.signature..................",
88+
+ expected: nil,
89+
+ isValid: false,
90+
+ },
91+
+ }
92+
+
93+
+ for _, tt := range tests {
94+
+ t.Run(tt.name, func(t *testing.T) {
95+
+ parts, ok := splitToken(tt.input)
96+
+ if ok != tt.isValid {
97+
+ t.Errorf("expected %t, got %t", tt.isValid, ok)
98+
+ }
99+
+ if ok {
100+
+ for i, part := range tt.expected {
101+
+ if parts[i] != part {
102+
+ t.Errorf("expected %s, got %s", part, parts[i])
103+
+ }
104+
+ }
105+
+ }
106+
+ })
107+
+ }
108+
+}
109+
diff --git a/vendor/github.com/dgrijalva/jwt-go/parser.go b/vendor/github.com/dgrijalva/jwt-go/parser.go
110+
index 9fddb7d..dbee074 100644
111+
--- a/vendor/github.com/dgrijalva/jwt-go/parser.go
112+
+++ b/vendor/github.com/dgrijalva/jwt-go/parser.go
113+
@@ -7,6 +7,8 @@ import (
114+
"strings"
115+
)
116+
117+
+const tokenDelimiter = "."
118+
+
119+
type Parser struct {
120+
ValidMethods []string // If populated, only these methods will be considered valid
121+
UseJSONNumber bool // Use JSON Number format in JSON decoder
122+
@@ -99,9 +101,10 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf
123+
// been checked previously in the stack) and you want to extract values from
124+
// it.
125+
func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) {
126+
- parts = strings.Split(tokenString, ".")
127+
- if len(parts) != 3 {
128+
- return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed)
129+
+ var ok bool
130+
+ parts, ok = splitToken(tokenString)
131+
+ if !ok {
132+
+ return nil, nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed)
133+
}
134+
135+
token = &Token{Raw: tokenString}
136+
@@ -151,3 +154,30 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke
137+
138+
return token, parts, nil
139+
}
140+
+
141+
+// splitToken splits a token string into three parts: header, claims, and signature. It will only
142+
+// return true if the token contains exactly two delimiters and three parts. In all other cases, it
143+
+// will return nil parts and false.
144+
+func splitToken(token string) ([]string, bool) {
145+
+ parts := make([]string, 3)
146+
+ header, remain, ok := strings.Cut(token, tokenDelimiter)
147+
+ if !ok {
148+
+ return nil, false
149+
+ }
150+
+ parts[0] = header
151+
+ claims, remain, ok := strings.Cut(remain, tokenDelimiter)
152+
+ if !ok {
153+
+ return nil, false
154+
+ }
155+
+ parts[1] = claims
156+
+ // One more cut to ensure the signature is the last part of the token and there are no more
157+
+ // delimiters. This avoids an issue where malicious input could contain additional delimiters
158+
+ // causing unecessary overhead parsing tokens.
159+
+ signature, _, unexpected := strings.Cut(remain, tokenDelimiter)
160+
+ if unexpected {
161+
+ return nil, false
162+
+ }
163+
+ parts[2] = signature
164+
+
165+
+ return parts, true
166+
+}
167+
--
168+
2.45.4
169+
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
From a2aa394b94f7201506c00cd6b0b64a2dca2ce6b7 Mon Sep 17 00:00:00 2001
2+
From: Roland Shoemaker <roland@golang.org>
3+
Date: Mon, 29 Sep 2025 16:33:18 -0700
4+
Subject: [PATCH] html: impose open element stack size limit
5+
6+
The HTML specification contains a number of algorithms which are
7+
quadratic in complexity by design. Instead of adding complicated
8+
workarounds to prevent these cases from becoming extremely expensive in
9+
pathological cases, we impose a limit of 512 to the size of the stack of
10+
open elements. It is extremely unlikely that non-adversarial HTML
11+
documents will ever hit this limit (but if we see cases of this, we may
12+
want to make the limit configurable via a ParseOption).
13+
14+
Thanks to Guido Vranken and Jakub Ciolek for both independently
15+
reporting this issue.
16+
17+
Fixes CVE-2025-47911
18+
Fixes golang/go#75682
19+
20+
Change-Id: I890517b189af4ffbf427d25d3fde7ad7ec3509ad
21+
Reviewed-on: https://go-review.googlesource.com/c/net/+/709876
22+
Reviewed-by: Damien Neil <dneil@google.com>
23+
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
24+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
25+
Upstream-reference: https://github.com/golang/net/commit/59706cdaa8f95502fdec64b67b4c61d6ca58727d.patch
26+
---
27+
vendor/golang.org/x/net/html/escape.go | 2 +-
28+
vendor/golang.org/x/net/html/parse.go | 21 +++++++++++++++++----
29+
2 files changed, 18 insertions(+), 5 deletions(-)
30+
31+
diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go
32+
index d856139..8edd4c4 100644
33+
--- a/vendor/golang.org/x/net/html/escape.go
34+
+++ b/vendor/golang.org/x/net/html/escape.go
35+
@@ -218,7 +218,7 @@ func escape(w writer, s string) error {
36+
case '\r':
37+
esc = "&#13;"
38+
default:
39+
- panic("unrecognized escape character")
40+
+ panic("html: unrecognized escape character")
41+
}
42+
s = s[i+1:]
43+
if _, err := w.WriteString(esc); err != nil {
44+
diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go
45+
index 851dc42..ac1fac1 100644
46+
--- a/vendor/golang.org/x/net/html/parse.go
47+
+++ b/vendor/golang.org/x/net/html/parse.go
48+
@@ -231,7 +231,14 @@ func (p *parser) addChild(n *Node) {
49+
}
50+
51+
if n.Type == ElementNode {
52+
- p.oe = append(p.oe, n)
53+
+ p.insertOpenElement(n)
54+
+ }
55+
+}
56+
+
57+
+func (p *parser) insertOpenElement(n *Node) {
58+
+ p.oe = append(p.oe, n)
59+
+ if len(p.oe) > 512 {
60+
+ panic("html: open stack of elements exceeds 512 nodes")
61+
}
62+
}
63+
64+
@@ -786,7 +793,7 @@ func afterHeadIM(p *parser) bool {
65+
p.im = inFramesetIM
66+
return true
67+
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
68+
- p.oe = append(p.oe, p.head)
69+
+ p.insertOpenElement(p.head)
70+
defer p.oe.remove(p.head)
71+
return inHeadIM(p)
72+
case a.Head:
73+
@@ -2273,9 +2280,13 @@ func (p *parser) parseCurrentToken() {
74+
}
75+
}
76+
77+
-func (p *parser) parse() error {
78+
+func (p *parser) parse() (err error) {
79+
+ defer func() {
80+
+ if panicErr := recover(); panicErr != nil {
81+
+ err = fmt.Errorf("%s", panicErr)
82+
+ }
83+
+ }()
84+
// Iterate until EOF. Any other error will cause an early return.
85+
- var err error
86+
for err != io.EOF {
87+
// CDATA sections are allowed only in foreign content.
88+
n := p.oe.top()
89+
@@ -2304,6 +2315,8 @@ func (p *parser) parse() error {
90+
// <tag>s. Conversely, explicit <tag>s in r's data can be silently dropped,
91+
// with no corresponding node in the resulting tree.
92+
//
93+
+// Parse will reject HTML that is nested deeper than 512 elements.
94+
+//
95+
// The input is assumed to be UTF-8 encoded.
96+
func Parse(r io.Reader) (*Node, error) {
97+
return ParseWithOptions(r)
98+
--
99+
2.45.4
100+

SPECS/application-gateway-kubernetes-ingress/application-gateway-kubernetes-ingress.spec

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Summary: Application Gateway Ingress Controller
33
Name: application-gateway-kubernetes-ingress
44
Version: 1.4.0
5-
Release: 26%{?dist}
5+
Release: 27%{?dist}
66
License: MIT
77
Vendor: Microsoft Corporation
88
Distribution: Mariner
@@ -32,6 +32,8 @@ Patch2: CVE-2021-44716.patch
3232
Patch3: CVE-2022-32149.patch
3333
Patch4: CVE-2024-45338.patch
3434
Patch5: CVE-2024-51744.patch
35+
Patch6: CVE-2025-30204.patch
36+
Patch7: CVE-2025-47911.patch
3537

3638
BuildRequires: golang
3739
%if %{with_check}
@@ -70,6 +72,9 @@ cp appgw-ingress %{buildroot}%{_bindir}/
7072
%{_bindir}/appgw-ingress
7173

7274
%changelog
75+
* Wed Feb 18 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.4.0-27
76+
- Patch for CVE-2025-30204, CVE-2025-47911
77+
7378
* Thu Sep 04 2025 Akhila Guruju <v-guakhila@microsoft.com> - 1.4.0-26
7479
- Bump release to rebuild with golang
7580

@@ -129,7 +134,7 @@ cp appgw-ingress %{buildroot}%{_bindir}/
129134
* Fri Feb 03 2023 CBL-Mariner Servicing Account <cblmargh@microsoft.com> - 1.4.0-8
130135
- Bump release to rebuild with go 1.19.5
131136

132-
* Tues Jan 24 2023 Adit Jha <aditjha@microsoft.com> - 1.4.0-7
137+
* Tue Jan 24 2023 Adit Jha <aditjha@microsoft.com> - 1.4.0-7
133138
- Bump release to rebuild vendor repoistory which contain patch fix for CVE-2021-4235, CVE-2022-3064
134139

135140
* Wed Jan 18 2023 CBL-Mariner Servicing Account <cblmargh@microsoft.com> - 1.4.0-6

0 commit comments

Comments
 (0)