Skip to content

Commit a983093

Browse files
[High] Patch docker-buildx for CVE-2026-39833 (microsoft#17590)
Co-authored-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
1 parent f927414 commit a983093

9 files changed

Lines changed: 603 additions & 33 deletions
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
From a41d5f6f770016cd9c9a05d51a9b4a578e64e3ba Mon Sep 17 00:00:00 2001
2+
From: Roland Shoemaker <roland@golang.org>
3+
Date: Tue, 12 May 2026 15:36:39 -0400
4+
Subject: [PATCH] html: improve Noah's Ark clause performance
5+
6+
Instead of iterating over each element in the stack, and checking each
7+
attribute against each other attribute in a ~cubic fashion, sort the
8+
attributes and just use slices.Equal.
9+
10+
Thanks to IPC Labs for reporting this issue.
11+
12+
Fixes CVE-2026-25680
13+
14+
Change-Id: Iec3513ba0b5da4f28f1359d24846401b9ab76ee3
15+
Reviewed-on: https://go-review.googlesource.com/c/net/+/781702
16+
TryBot-Bypass: Roland Shoemaker <roland@golang.org>
17+
Reviewed-by: Nicholas Husin <nsh@golang.org>
18+
Reviewed-by: Neal Patel <nealpatel@google.com>
19+
Reviewed-by: Nicholas Husin <husin@google.com>
20+
Auto-Submit: Gopher Robot <gobot@golang.org>
21+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
22+
Upstream-reference: https://github.com/golang/net/commit/08be507abce89191d78cd49da60f4501fc910472.patch
23+
---
24+
vendor/golang.org/x/net/html/parse.go | 34 ++++++++++++++++-----------
25+
1 file changed, 20 insertions(+), 14 deletions(-)
26+
27+
diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go
28+
index 3392845..4bd5e6d 100644
29+
--- a/vendor/golang.org/x/net/html/parse.go
30+
+++ b/vendor/golang.org/x/net/html/parse.go
31+
@@ -5,9 +5,11 @@
32+
package html
33+
34+
import (
35+
+ "cmp"
36+
"errors"
37+
"fmt"
38+
"io"
39+
+ "slices"
40+
"strings"
41+
42+
a "golang.org/x/net/html/atom"
43+
@@ -328,6 +330,14 @@ func (p *parser) addText(text string) {
44+
})
45+
}
46+
47+
+func attrCompare(a, b Attribute) int {
48+
+ return cmp.Or(
49+
+ cmp.Compare(a.Namespace, b.Namespace),
50+
+ cmp.Compare(a.Key, b.Key),
51+
+ cmp.Compare(a.Val, b.Val),
52+
+ )
53+
+}
54+
+
55+
// addElement adds a child element based on the current token.
56+
func (p *parser) addElement() {
57+
p.addChild(&Node{
58+
@@ -343,6 +353,10 @@ func (p *parser) addFormattingElement() {
59+
tagAtom, attr := p.tok.DataAtom, p.tok.Attr
60+
p.addElement()
61+
62+
+ // In order to optimize the search, we need the attributes to be sorted, so we
63+
+ // can just use slices.Equal.
64+
+ slices.SortFunc(attr, attrCompare)
65+
+
66+
// Implement the Noah's Ark clause, but with three per family instead of two.
67+
identicalElements := 0
68+
findIdenticalElements:
69+
@@ -360,19 +374,7 @@ findIdenticalElements:
70+
if n.DataAtom != tagAtom {
71+
continue
72+
}
73+
- if len(n.Attr) != len(attr) {
74+
- continue
75+
- }
76+
- compareAttributes:
77+
- for _, t0 := range n.Attr {
78+
- for _, t1 := range attr {
79+
- if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {
80+
- // Found a match for this attribute, continue with the next attribute.
81+
- continue compareAttributes
82+
- }
83+
- }
84+
- // If we get here, there is no attribute that matches a.
85+
- // Therefore the element is not identical to the new one.
86+
+ if !slices.Equal(n.Attr, attr) {
87+
continue findIdenticalElements
88+
}
89+
90+
@@ -382,7 +384,11 @@ findIdenticalElements:
91+
}
92+
}
93+
94+
- p.afe = append(p.afe, p.top())
95+
+ // Sort the attributes to optimize future identical-element searches.
96+
+ top := p.top()
97+
+ slices.SortFunc(top.Attr, attrCompare)
98+
+
99+
+ p.afe = append(p.afe, top)
100+
}
101+
102+
// Section 12.2.4.3.
103+
--
104+
2.45.4
105+
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
From ad069ba0be8708962939d544ac5a30609ec70e1b Mon Sep 17 00:00:00 2001
2+
From: Roland Shoemaker <roland@golang.org>
3+
Date: Mon, 4 May 2026 11:47:15 -0700
4+
Subject: [PATCH] html: escape greater-than symbol in doctype identifiers
5+
6+
During parsing, we unescape character references. When rendering, we
7+
re-escape certain characters in certain scenarios in order to avoid
8+
token content causing unexpected parser behavior.
9+
10+
We appear to have not taken this into account when rendering DOCTYPE
11+
tokens, allowing ">" in PUBLIC/SYSTEM identifier strings, which trigger
12+
a abrupt-doctype-system-identifier parse error which immediately emits
13+
the current DOCTYPE token and then continues parsing in the data state.
14+
15+
This may cause bypass in HTML santizers which use the html package for
16+
parsing.
17+
18+
Thanks to ensy for reporting this issue.
19+
20+
Fixes CVE-2026-25681
21+
22+
Change-Id: I1d5be92129d17bfbf0917148db2672d57c224a18
23+
Reviewed-on: https://go-review.googlesource.com/c/net/+/781703
24+
Reviewed-by: Neal Patel <nealpatel@google.com>
25+
Reviewed-by: Nicholas Husin <nsh@golang.org>
26+
TryBot-Bypass: Roland Shoemaker <roland@golang.org>
27+
Auto-Submit: Gopher Robot <gobot@golang.org>
28+
Reviewed-by: Nicholas Husin <husin@google.com>
29+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
30+
Upstream-reference: https://github.com/golang/net/commit/4ece7b612ad44ad6c4d5e0d5d4df9c18cc211905.patch
31+
---
32+
vendor/golang.org/x/net/html/render.go | 19 +++++++++++++------
33+
.../html/testdata/go/doctype_named_entity.dat | 8 ++++++++
34+
2 files changed, 21 insertions(+), 6 deletions(-)
35+
create mode 100644 vendor/golang.org/x/net/html/testdata/go/doctype_named_entity.dat
36+
37+
diff --git a/vendor/golang.org/x/net/html/render.go b/vendor/golang.org/x/net/html/render.go
38+
index e8c1233..f3740cc 100644
39+
--- a/vendor/golang.org/x/net/html/render.go
40+
+++ b/vendor/golang.org/x/net/html/render.go
41+
@@ -113,14 +113,14 @@ func render1(w writer, n *Node) error {
42+
if _, err := w.WriteString(" PUBLIC "); err != nil {
43+
return err
44+
}
45+
- if err := writeQuoted(w, p); err != nil {
46+
+ if err := writeDoctypeQuoted(w, p); err != nil {
47+
return err
48+
}
49+
if s != "" {
50+
if err := w.WriteByte(' '); err != nil {
51+
return err
52+
}
53+
- if err := writeQuoted(w, s); err != nil {
54+
+ if err := writeDoctypeQuoted(w, s); err != nil {
55+
return err
56+
}
57+
}
58+
@@ -128,7 +128,7 @@ func render1(w writer, n *Node) error {
59+
if _, err := w.WriteString(" SYSTEM "); err != nil {
60+
return err
61+
}
62+
- if err := writeQuoted(w, s); err != nil {
63+
+ if err := writeDoctypeQuoted(w, s); err != nil {
64+
return err
65+
}
66+
}
67+
@@ -251,19 +251,26 @@ func childTextNodesAreLiteral(n *Node) bool {
68+
}
69+
}
70+
71+
-// writeQuoted writes s to w surrounded by quotes. Normally it will use double
72+
+// writeDoctypeQuoted writes s to w surrounded by quotes. Normally it will use double
73+
// quotes, but if s contains a double quote, it will use single quotes.
74+
+// If s contains any '>' characters, they are replaced with &gt; in order
75+
+// to prevent triggering an abrupt-doctype-system-identifier parse error.
76+
// It is used for writing the identifiers in a doctype declaration.
77+
// In valid HTML, they can't contain both types of quotes.
78+
-func writeQuoted(w writer, s string) error {
79+
+func writeDoctypeQuoted(w writer, s string) error {
80+
var q byte = '"'
81+
if strings.Contains(s, `"`) {
82+
+ // parseDoctype will never produce a Node with both quote types, but a user
83+
+ // can construct their own Node that violates this assumption.
84+
+ if strings.Contains(s, `'`) {
85+
+ return errors.New("doctype contains both quote types, cannot be safely rendered")
86+
+ }
87+
q = '\''
88+
}
89+
if err := w.WriteByte(q); err != nil {
90+
return err
91+
}
92+
- if _, err := w.WriteString(s); err != nil {
93+
+ if _, err := w.WriteString(strings.ReplaceAll(s, ">", "&gt;")); err != nil {
94+
return err
95+
}
96+
if err := w.WriteByte(q); err != nil {
97+
diff --git a/vendor/golang.org/x/net/html/testdata/go/doctype_named_entity.dat b/vendor/golang.org/x/net/html/testdata/go/doctype_named_entity.dat
98+
new file mode 100644
99+
index 0000000..a8bd963
100+
--- /dev/null
101+
+++ b/vendor/golang.org/x/net/html/testdata/go/doctype_named_entity.dat
102+
@@ -0,0 +1,8 @@
103+
+#data
104+
+<!DOCTYPE &gt; PUBLIC "&gt;" "&gt;">
105+
+#errors
106+
+#document
107+
+| <!DOCTYPE > ">" ">">
108+
+| <html>
109+
+| <head>
110+
+| <body>
111+
--
112+
2.45.4
113+
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
From dea4d512416306154b3fa843d1df540d61bace47 Mon Sep 17 00:00:00 2001
2+
From: Nicola Murino <nicola.murino@gmail.com>
3+
Date: Sun, 1 Mar 2026 11:49:28 +0100
4+
Subject: [PATCH] ssh: prevent memory leak when rejecting channels
5+
6+
When a server rejects an incoming channel request via
7+
NewChannel.Reject, the channel is left in the multiplexer's
8+
channel list. Because the channel is never explicitly removed or
9+
closed, its internal buffers and sync primitives remain allocated
10+
for the lifetime of the SSH connection.
11+
12+
A malicious client could exploit this behavior by repeatedly
13+
requesting to open channels that are destined to be rejected,
14+
causing unbounded memory growth and potentially leading to a
15+
Denial of Service (DoS) via resource exhaustion.
16+
17+
This change fixes the leak by calling ch.mux.chanList.remove
18+
within the Reject method, removing the channel from the list and allowing the
19+
garbage collector to reclaim the associated memory immediately.
20+
21+
Fixes golang/go#35127
22+
Fixes CVE-2026-3982
23+
24+
Change-Id: Iaa177f5dfd151812dd404e528a4a1c77527a0e29
25+
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/781320
26+
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
27+
Reviewed-by: Roland Shoemaker <roland@golang.org>
28+
Reviewed-by: Nicholas Husin <nsh@golang.org>
29+
Reviewed-by: Nicholas Husin <husin@google.com>
30+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
31+
Upstream-reference: https://github.com/golang/crypto/commit/6c195c8a97ae3d91a366ebdd7787d5faa64bf42a.patch
32+
---
33+
vendor/golang.org/x/crypto/ssh/channel.go | 12 +++++++++++-
34+
1 file changed, 11 insertions(+), 1 deletion(-)
35+
36+
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
37+
index 3967b65..77bac19 100644
38+
--- a/vendor/golang.org/x/crypto/ssh/channel.go
39+
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
40+
@@ -536,7 +536,17 @@ func (ch *channel) Reject(reason RejectionReason, message string) error {
41+
Language: "en",
42+
}
43+
ch.decided = true
44+
- return ch.sendMessage(reject)
45+
+ err := ch.sendMessage(reject)
46+
+
47+
+ // Remove the channel from the mux to prevent memory leaks.
48+
+ // Do not call ch.close() here: no goroutine holds a reference to a
49+
+ // rejected channel's internal channels (msg, incomingRequests), so
50+
+ // removing it from chanList is sufficient for GC. Calling close()
51+
+ // would race with the mux loop goroutine (handlePacket or dropAll),
52+
+ // causing a panic from closing an already-closed channel.
53+
+ ch.mux.chanList.remove(ch.localId)
54+
+
55+
+ return err
56+
}
57+
58+
func (ch *channel) Read(data []byte) (int, error) {
59+
--
60+
2.45.4
61+
Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,39 @@
1-
From e9da9a48632aecf8d45a351274dc2f36269140c2 Mon Sep 17 00:00:00 2001
1+
From e3d1254f1e7e60baa086142c46174bf6d8d0fe50 Mon Sep 17 00:00:00 2001
22
From: Nicola <nicola.murino@gmail.com>
3-
Date: Tue, 27 Jan 2026 12:15:18 +0100
4-
Subject: [PATCH] ssh/agent: preserve constraint extensions when adding keys
3+
Date: Sun, 1 Feb 2026 14:55:12 +0100
4+
Subject: [PATCH] ssh/agent: don't accept keys with unsupported constraints
55

6-
The client Add method only serialized the lifetime and confirm
7-
constraints and silently dropped AddedKey.ConstraintExtensions before
8-
sending the SSH_AGENTC_ADD_IDENTITY request. As a result the remote
9-
agent always received the key with no extension constraints, regardless
10-
of what the caller requested.
6+
The in-memory keyring cannot enforce constraint extensions, so silently
7+
accepting a key that carries them gave callers a false sense of
8+
restriction. Refuse keys with constraint extensions instead: a key
9+
whose constraints cannot be enforced must not be loaded. This behavior
10+
is consistent with OpenSSH.
1111

12-
Applications that add a key believing custom constraint extensions
13-
(such as restrict-destination-v00@openssh.com) would be enforced
14-
instead loaded a completely unrestricted key into the agent. For
15-
example, an administrator forwarding their agent into an untrusted jump
16-
host and trying to limit the forwarded key with restrict-destination
17-
never had that restriction reach the agent: any user or compromised
18-
process on that host could make the agent sign arbitrary challenges.
19-
20-
Serialize each entry in key.ConstraintExtensions as an
21-
agentConstrainExtension constraint so the constraints reach the agent,
22-
and add a round-trip regression test that verifies the extensions
23-
survive client serialization and server parsing.
12+
This is a deliberate behavior change: keyring.Add previously accepted
13+
and ignored ConstraintExtensions and now returns an error.
2414

2515
This issue was found during a security audit by NCC Group Cryptography
2616
Services, sponsored by Teleport.
2717

28-
Updates CVE-2026-39832
29-
Updates golang/go#79435
18+
Fixes CVE-2026-39832
19+
Fixes golang/go#79435
3020

31-
Change-Id: I14c5583b106cbf0d282d2ba01e000e0f586f08c7
32-
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/778640
21+
Change-Id: I6ca4f1c29f8edfabb287fe07299641f70896d5fe
22+
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/778641
23+
Auto-Submit: Neal Patel <nealpatel@google.com>
24+
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
3325
Reviewed-by: Neal Patel <neal@golang.org>
26+
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
3427
Reviewed-by: Neal Patel <nealpatel@google.com>
35-
Reviewed-by: Keith Randall <khr@google.com>
36-
Reviewed-by: David Chase <drchase@google.com>
37-
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
38-
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
39-
Upstream-reference: https://github.com/golang/crypto/commit/a1ce0fee129597fdea8dfd58d71b6b607de6bdce.patch
28+
29+
This CVE needs 2 commits for the fix.
30+
Upstream Patch reference:
31+
1. https://github.com/golang/crypto/commit/e3d1254f1e7e60baa086142c46174bf6d8d0fe50.patch
32+
2. https://github.com/golang/crypto/commit/a1ce0fee129597fdea8dfd58d71b6b607de6bdce.patch
4033
---
41-
vendor/golang.org/x/crypto/ssh/agent/client.go | 7 +++++++
42-
1 file changed, 7 insertions(+)
34+
vendor/golang.org/x/crypto/ssh/agent/client.go | 7 +++++++
35+
vendor/golang.org/x/crypto/ssh/agent/keyring.go | 12 +++++++++---
36+
2 files changed, 16 insertions(+), 3 deletions(-)
4337

4438
diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go
4539
index 6dc73e0..d9e7f73 100644
@@ -59,6 +53,35 @@ index 6dc73e0..d9e7f73 100644
5953
cert := key.Certificate
6054
if cert == nil {
6155
return c.insertKey(key.PrivateKey, key.Comment, constraints)
56+
diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go
57+
index 21bfa87..64bc105 100644
58+
--- a/vendor/golang.org/x/crypto/ssh/agent/keyring.go
59+
+++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go
60+
@@ -143,15 +143,21 @@ func (r *keyring) List() ([]*Key, error) {
61+
return ids, nil
62+
}
63+
64+
-// Insert adds a private key to the keyring. If a certificate
65+
-// is given, that certificate is added as public key. Note that
66+
-// any constraints given are ignored.
67+
+// Add adds a private key to the keyring. If a certificate is given, that
68+
+// certificate is added as public key.
69+
+//
70+
+// Add returns an error if key contains ConstraintExtensions.
71+
func (r *keyring) Add(key AddedKey) error {
72+
r.mu.Lock()
73+
defer r.mu.Unlock()
74+
if r.locked {
75+
return errLocked
76+
}
77+
+
78+
+ if len(key.ConstraintExtensions) > 0 {
79+
+ return errors.New("agent: constraint extensions are present but not supported")
80+
+ }
81+
+
82+
signer, err := ssh.NewSignerFromKey(key.PrivateKey)
83+
84+
if err != nil {
6285
--
63-
2.45.4
86+
2.43.0
6487

0 commit comments

Comments
 (0)