Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch docker-compose for CVE-2025-22869 & CVE-2024-10846 [High] #12725

Open
wants to merge 1 commit into
base: fasttrack/3.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions SPECS/docker-compose/CVE-2024-10846.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
From 217663fd8fd2b7b789c9f877bbd9781d887a6b07 Mon Sep 17 00:00:00 2001
From: Kanishk-Bansal <kbkanishk975@gmail.com>
Date: Mon, 3 Mar 2025 04:54:06 +0000
Subject: [PATCH] CVE-2024-10846
Upstream Reference: https://github.com/compose-spec/compose-go/pull/703
---
.../compose-go/v2/loader/reset.go | 28 ++++++++++++++++---
1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go b/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
index 2b7f04c..213d0e8 100644
--- a/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
+++ b/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
@@ -26,13 +26,15 @@ import (
)

type ResetProcessor struct {
- target interface{}
- paths []tree.Path
+ target interface{}
+ paths []tree.Path
+ visitedNodes map[*yaml.Node]string
}

// UnmarshalYAML implement yaml.Unmarshaler
func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {
resolved, err := p.resolveReset(value, tree.NewPath())
+ p.visitedNodes = nil
if err != nil {
return err
}
@@ -41,10 +43,28 @@ func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {

// resolveReset detects `!reset` tag being set on yaml nodes and record position in the yaml tree
func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.Node, error) {
+ pathStr := path.String()
// If the path contains "<<", removing the "<<" element and merging the path
- if strings.Contains(path.String(), ".<<") {
- path = tree.NewPath(strings.Replace(path.String(), ".<<", "", 1))
+ if strings.Contains(pathStr, ".<<") {
+ path = tree.NewPath(strings.Replace(pathStr, ".<<", "", 1))
}
+
+ // Check for cycle
+ if p.visitedNodes == nil {
+ p.visitedNodes = make(map[*yaml.Node]string)
+ }
+
+ // Check for cycle by seeing if the node has already been visited at this path
+ if previousPath, found := p.visitedNodes[node]; found {
+ // If the current node has been visited, we have a cycle if the previous path is a prefix
+ if strings.HasPrefix(pathStr, previousPath) {
+ return nil, fmt.Errorf("cycle detected at path: %s", pathStr)
+ }
+ }
+
+ // Mark the current node as visited
+ p.visitedNodes[node] = pathStr
+
// If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags
if node.Kind == yaml.AliasNode {
return p.resolveReset(node.Alias, path)
--
2.45.2

140 changes: 140 additions & 0 deletions SPECS/docker-compose/CVE-2025-22869.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
From 041b89a18f81265899e42e6801f830c101a96120 Mon Sep 17 00:00:00 2001
From: Kanishk-Bansal <kbkanishk975@gmail.com>
Date: Sun, 2 Mar 2025 13:46:00 +0000
Subject: [PATCH] CVE-2025-22869

Upstream Reference : https://github.com/golang/crypto/commit/7292932d45d55c7199324ab0027cc86e8198aa22

ssh: limit the size of the internal packet queue while waiting for KEX

In the SSH protocol, clients and servers execute the key exchange to
generate one-time session keys used for encryption and authentication.
The key exchange is performed initially after the connection is
established and then periodically after a configurable amount of data.
While a key exchange is in progress, we add the received packets to an
internal queue until we receive SSH_MSG_KEXINIT from the other side.
This can result in high memory usage if the other party is slow to
respond to the SSH_MSG_KEXINIT packet, or memory exhaustion if a
malicious client never responds to an SSH_MSG_KEXINIT packet during a
large file transfer.
We now limit the internal queue to 64 packets: this means 2MB with the
typical 32KB packet size.
When the internal queue is full we block further writes until the
pending key exchange is completed or there is a read or write error.

Thanks to Yuichi Watanabe for reporting this issue.

Change-Id: I1ce2214cc16e08b838d4bc346c74c72addafaeec
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/652135
Reviewed-by: Neal Patel <nealpatel@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

---
vendor/golang.org/x/crypto/ssh/handshake.go | 47 ++++++++++++++++-----
1 file changed, 37 insertions(+), 10 deletions(-)

diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 70a7369..e14eb6c 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -24,6 +24,11 @@ const debugHandshake = false
// quickly.
const chanSize = 16

+// maxPendingPackets sets the maximum number of packets to queue while waiting
+// for KEX to complete. This limits the total pending data to maxPendingPackets
+// * maxPacket bytes, which is ~16.8MB.
+const maxPendingPackets = 64
+
// keyingTransport is a packet based transport that supports key
// changes. It need not be thread-safe. It should pass through
// msgNewKeys in both directions.
@@ -58,11 +63,19 @@ type handshakeTransport struct {
incoming chan []byte
readError error

- mu sync.Mutex
- writeError error
- sentInitPacket []byte
- sentInitMsg *kexInitMsg
- pendingPackets [][]byte // Used when a key exchange is in progress.
+ mu sync.Mutex
+ // Condition for the above mutex. It is used to notify a completed key
+ // exchange or a write failure. Writes can wait for this condition while a
+ // key exchange is in progress.
+ writeCond *sync.Cond
+ writeError error
+ sentInitPacket []byte
+ sentInitMsg *kexInitMsg
+ // Used to queue writes when a key exchange is in progress. The length is
+ // limited by pendingPacketsSize. Once full, writes will block until the key
+ // exchange is completed or an error occurs. If not empty, it is emptied
+ // all at once when the key exchange is completed in kexLoop.
+ pendingPackets [][]byte
writePacketsLeft uint32
writeBytesLeft int64

@@ -114,6 +127,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,

config: config,
}
+ t.writeCond = sync.NewCond(&t.mu)
t.resetReadThresholds()
t.resetWriteThresholds()

@@ -236,6 +250,7 @@ func (t *handshakeTransport) recordWriteError(err error) {
defer t.mu.Unlock()
if t.writeError == nil && err != nil {
t.writeError = err
+ t.writeCond.Broadcast()
}
}

@@ -339,6 +354,8 @@ write:
}
}
t.pendingPackets = t.pendingPackets[:0]
+ // Unblock writePacket if waiting for KEX.
+ t.writeCond.Broadcast()
t.mu.Unlock()
}

@@ -526,11 +543,20 @@ func (t *handshakeTransport) writePacket(p []byte) error {
}

if t.sentInitMsg != nil {
- // Copy the packet so the writer can reuse the buffer.
- cp := make([]byte, len(p))
- copy(cp, p)
- t.pendingPackets = append(t.pendingPackets, cp)
- return nil
+ if len(t.pendingPackets) < maxPendingPackets {
+ // Copy the packet so the writer can reuse the buffer.
+ cp := make([]byte, len(p))
+ copy(cp, p)
+ t.pendingPackets = append(t.pendingPackets, cp)
+ return nil
+ }
+ for t.sentInitMsg != nil {
+ // Block and wait for KEX to complete or an error.
+ t.writeCond.Wait()
+ if t.writeError != nil {
+ return t.writeError
+ }
+ }
}

if t.writeBytesLeft > 0 {
@@ -547,6 +573,7 @@ func (t *handshakeTransport) writePacket(p []byte) error {

if err := t.pushPacket(p); err != nil {
t.writeError = err
+ t.writeCond.Broadcast()
}

return nil
--
2.45.2

7 changes: 6 additions & 1 deletion SPECS/docker-compose/docker-compose.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Summary: Define and run multi-container applications with Docker
Name: docker-compose
Version: 2.27.0
Release: 3%{?dist}
Release: 4%{?dist}
License: ASL 2.0
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -14,6 +14,8 @@ Source0: https://github.com/docker/compose/archive/refs/tags/v%{version}.
Source1: %{name}-%{version}-govendor-v1.tar.gz
Patch0: CVE-2024-45337.patch
Patch1: CVE-2024-45338.patch
Patch2: CVE-2025-22869.patch
Patch3: CVE-2024-10846.patch
BuildRequires: golang
Requires: docker-cli
Obsoletes: moby-compose < %{version}-%{release}
Expand Down Expand Up @@ -46,6 +48,9 @@ install -D -m0755 bin/build/docker-compose %{buildroot}/%{_libexecdir}/docker/cl
%{_libexecdir}/docker/cli-plugins/docker-compose

%changelog
* Mon Mar 03 2025 Kanishk Bansal <kanbansal@microsoft.com> - 2.27.0-4
- Fix CVE-2025-22869, CVE-2024-10846 with an upstream patch

* Tue Dec 31 2024 Rohit Rawat <rohitrawat@microsoft.com> - 2.27.0-3
- Add patch for CVE-2024-45338

Expand Down
Loading