Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package docker-stable for openSUSE:Factory checked in at 2026-06-22 17:28:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/docker-stable (Old) and /work/SRC/openSUSE:Factory/.docker-stable.new.1956 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "docker-stable" Mon Jun 22 17:28:14 2026 rev:18 rq:1360739 version:unknown Changes: -------- --- /work/SRC/openSUSE:Factory/docker-stable/docker-stable.changes 2026-02-25 21:10:41.982488460 +0100 +++ /work/SRC/openSUSE:Factory/.docker-stable.new.1956/docker-stable.changes 2026-06-22 17:29:15.173355979 +0200 @@ -1,0 +2,48 @@ +Thu Jun 18 02:50:21 UTC 2026 - Madhankumar Chellamuthu <[email protected]> + +- grpc: enforce strict path checking for incoming requests on the server + Backport of <grpc/grpc-go@72186f1> + (bsc#1260279, CVE-2026-33186) + * 0023-CVE-2026-33186-grpc-enforce-strict-path-checking-for.patch + +- http2: prevent hanging Transport due to bad SETTINGS + Backport of <golang/net@1e71bd8> + (bsc#1265782, CVE-2026-33814) + * 0024-CVE-2026-33814-http2-prevent-hanging-Transport-due-t.patch + +- idna: update from x/text, fix ToUnicode and all-ASCII xn-- labels + Backport of <golang/net@8c4c965#diff-6b95b04ab0c83612198e99ffb2f4411f899daf14b618d907bcff2196a9af8e6b> + * 0025-CVE-2026-39821-idna-update-from-x-text-fix-ToUnicode.patch + +- daemon: Decompress archives before entering container filesystem + Backport of <<moby@2022313> + (bsc#1267827, CVE-2026-41567) + * 0026-CVE-2026-41567-daemon-Decompress-archives-before-ent.patch + +------------------------------------------------------------------- +Tue Jun 2 05:13:15 UTC 2026 - Madhankumar Chellamuthu <[email protected]> + +- fix for Privilege validation bypass during plugin + Backport of <https://github.com/moby/moby/commit/99a095ecf04e8849318f2811bb3f687905eab09b> + (bsc#1265907, CVE-2026-33997) + * 0021-CVE-2026-33997-fix-for-Privilege-validation-bypass-d.patch + +- fix for Authz zero length regression + Backport of <https://github.com/moby/moby/commit/e89edb19ad7de0407a5d31e3111cb01aa10b5a38> + (bsc#1265929, CVE-2026-34040) + * 0022-CVE-2026-34040-fix-for-Authz-zero-length-regression.patch + +------------------------------------------------------------------- +Thu Apr 30 10:58:12 UTC 2026 - Madhankumar Chellamuthu <[email protected]> + +- executor: validate container IDs centrally + Backport of <https://github.com/moby/buildkit/commit/45b038cd0b2ec2d34013ce0f085522276f7ee0d8>. + (bsc#1261078, CVE-2026-33748) + * 0019-CVE-2026-33748-Fix-git-normalize-and-validate-subdir.patch + +- git: normalize and validate subdir paths + Backport of <https://github.com/moby/buildkit/commit/099cf80f5ebc935c48d2925499bffe703a54cff4>. + (bsc#1260967, CVE-2026-33747) + * 0020-CVE-2026-33747-Fix-executor-validate-container-IDs-c.patch + +------------------------------------------------------------------- New: ---- 0019-CVE-2026-33748-Fix-git-normalize-and-validate-subdir.patch 0020-CVE-2026-33747-Fix-executor-validate-container-IDs-c.patch 0021-CVE-2026-33997-fix-for-Privilege-validation-bypass-d.patch 0022-CVE-2026-34040-fix-for-Authz-zero-length-regression.patch 0023-CVE-2026-33186-grpc-enforce-strict-path-checking-for.patch 0024-CVE-2026-33814-http2-prevent-hanging-Transport-due-t.patch 0025-CVE-2026-39821-idna-update-from-x-text-fix-ToUnicode.patch 0026-CVE-2026-41567-daemon-Decompress-archives-before-ent.patch ----------(New B)---------- New: (bsc#1261078, CVE-2026-33748) * 0019-CVE-2026-33748-Fix-git-normalize-and-validate-subdir.patch New: (bsc#1260967, CVE-2026-33747) * 0020-CVE-2026-33747-Fix-executor-validate-container-IDs-c.patch New: (bsc#1265907, CVE-2026-33997) * 0021-CVE-2026-33997-fix-for-Privilege-validation-bypass-d.patch New: (bsc#1265929, CVE-2026-34040) * 0022-CVE-2026-34040-fix-for-Authz-zero-length-regression.patch New: (bsc#1260279, CVE-2026-33186) * 0023-CVE-2026-33186-grpc-enforce-strict-path-checking-for.patch New: (bsc#1265782, CVE-2026-33814) * 0024-CVE-2026-33814-http2-prevent-hanging-Transport-due-t.patch New: Backport of <golang/net@8c4c965#diff-6b95b04ab0c83612198e99ffb2f4411f899daf14b618d907bcff2196a9af8e6b> * 0025-CVE-2026-39821-idna-update-from-x-text-fix-ToUnicode.patch New: (bsc#1267827, CVE-2026-41567) * 0026-CVE-2026-41567-daemon-Decompress-archives-before-ent.patch ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ docker-stable.spec ++++++ --- /var/tmp/diff_new_pack.AYNMBo/_old 2026-06-22 17:29:17.777446693 +0200 +++ /var/tmp/diff_new_pack.AYNMBo/_new 2026-06-22 17:29:17.777446693 +0200 @@ -144,6 +144,24 @@ Patch212: 0017-CVE-2025-30204-fix-Remove-strings.Split-and-add-pars.patch # UPSTREAM: Backport of <https://go-review.googlesource.com/c/crypto/+/721961> bsc#1253904 Patch213: 0018-CVE-2025-58181-fix-vendor-crypto-ssh-3.patch +# UPSTREAM: Backport of <https://github.com/moby/buildkit/commit/45b038cd0b2ec2d34013ce0f085522276f7ee0d8> +# fixes CVE-2026-33748, bsc#1261078 +Patch214: 0019-CVE-2026-33748-Fix-git-normalize-and-validate-subdir.patch +# UPSTREAM: Backport of <https://github.com/moby/buildkit/commit/099cf80f5ebc935c48d2925499bffe703a54cff4> +# fixes CVE-2026-33747, bsc#1260967 +Patch215: 0020-CVE-2026-33747-Fix-executor-validate-container-IDs-c.patch +# UPSTREAM: Backport of <https://github.com/moby/moby/commit/99a095ecf04e8849318f2811bb3f687905eab09b> +Patch216: 0021-CVE-2026-33997-fix-for-Privilege-validation-bypass-d.patch +#UPSTREAM: Backport of <https://github.com/moby/moby/commit/e89edb19ad7de0407a5d31e3111cb01aa10b5a38> +Patch217: 0022-CVE-2026-34040-fix-for-Authz-zero-length-regression.patch +#UPSTREAM: Backport of <grpc/grpc-go@72186f1> +Patch218: 0023-CVE-2026-33186-grpc-enforce-strict-path-checking-for.patch +#UPSTREAM: Backport of <golang/net@1e71bd8> +Patch219: 0024-CVE-2026-33814-http2-prevent-hanging-Transport-due-t.patch +#UPSTREAM: Backport of <golang/net@8c4c965> +Patch220: 0025-CVE-2026-39821-idna-update-from-x-text-fix-ToUnicode.patch +#UPSTREAM: Backport of <moby@2022313> +Patch221: 0026-CVE-2026-41567-daemon-Decompress-archives-before-ent.patch # UPSTREAM: Backport of <https://github.com/moby/moby/pull/46307> and # <https://github.com/moby/moby/pull/49061>. Patch299: 0014-TESTS-backport-fixes-for-integration-tests.patch @@ -453,6 +471,22 @@ %patch -P212 -p1 # bsc#1253904 %patch -P213 -p1 +# bsc#1261078 +%patch -P214 -p1 +# bsc#1260967 +%patch -P215 -p1 +# bsc#1265907 +%patch -P216 -p1 +# bsc#1265929 +%patch -P217 -p1 +# bsc#1260279 +%patch -P218 -p1 +# bsc#1265782 +%patch -P219 -p1 +# bsc#1266625 +%patch -P220 -p1 +# bsc#1267827 +%patch -P221 -p1 %if %{with integration_tests} # integration-tests patches %patch -P299 -p1 ++++++ 0019-CVE-2026-33748-Fix-git-normalize-and-validate-subdir.patch ++++++ >From 993b3e57eca3035de88cab6883a1eefe4d929e35 Mon Sep 17 00:00:00 2001 From: rcmadhankumar <[email protected]> Date: Fri, 17 Apr 2026 14:31:21 +0530 Subject: [PATCH 1/2] CVE-2026-33748: Fix git: normalize and validate subdir paths -- CVE-2026-33748 Insufficient validation of Git URL fragment subdir components (<url>#<ref>:<subdir>, docs) may allow access to files outside the checked-out Git repository root. Possible access is limited to files on the same mounted filesystem. Fix: Normalize Git subdir fragments and validate checkout subdir components so each segment must be a real directory, preventing traversal and symlink escapes. Signed-off-by: Tonis Tiigi <[email protected]> (cherry picked from commit 8c994eb561a2646b35352e5663afecd225306214) (cherry picked from commit f756b3f8aa2f32b0986c1cbb6449a29fe22715d7) Reference: https://github.com/moby/buildkit/commit/45b038cd0b2ec2d34013ce0f085522276f7ee0d8 Fixes CVE-2026-33748 Fixes bsc#1261078 --- .../moby/buildkit/source/git/gitsource.go | 31 ++++++++++++++++++- .../moby/buildkit/source/gitidentifier.go | 5 ++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/vendor/github.com/moby/buildkit/source/git/gitsource.go b/vendor/github.com/moby/buildkit/source/git/gitsource.go index dd35fe55f7..14a21fd65f 100644 --- a/vendor/github.com/moby/buildkit/source/git/gitsource.go +++ b/vendor/github.com/moby/buildkit/source/git/gitsource.go @@ -486,7 +486,7 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out } }() - subdir := path.Clean(gs.src.Subdir) + subdir := path.Join("/", gs.src.Subdir) if subdir == "/" { subdir = "." } @@ -559,6 +559,11 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out return nil, errors.Wrapf(err, "failed to checkout remote %s", urlutil.RedactCredentials(gs.src.Remote)) } if subdir != "." { + subdir = filepath.FromSlash(subdir) + if err := validateDirsOnly(cd, subdir); err != nil { + return nil, errors.Wrapf(err, "invalid subdir %v", subdir) + } + d, err := os.Open(filepath.Join(cd, subdir)) if err != nil { return nil, errors.Wrapf(err, "failed to open subdir %v", subdir) @@ -761,3 +766,27 @@ func (md cacheRefMetadata) setGitSnapshot(key string) error { func (md cacheRefMetadata) setGitRemote(key string) error { return md.SetString(keyGitRemote, key, gitRemoteIndex+key) } + +// validateDirsOnly checks that the given subpath in the repository +// only contains directories without any symlinks or files. +func validateDirsOnly(root string, subpath string) error { + rel := filepath.Clean(subpath) + rel = strings.TrimPrefix(rel, string(filepath.Separator)) + if rel == "" || rel == "." { + return nil + } + + p := root + for _, part := range strings.Split(rel, string(filepath.Separator)) { + p = filepath.Join(p, part) + + fi, err := os.Lstat(p) + if err != nil { + return errors.Wrapf(err, "failed to lstat %q", p) + } + if !fi.IsDir() { + return errors.Errorf("git subpath %q contains non-directory %q", subpath, p) + } + } + return nil +} diff --git a/vendor/github.com/moby/buildkit/source/gitidentifier.go b/vendor/github.com/moby/buildkit/source/gitidentifier.go index 6055c94e2f..d72a378f15 100644 --- a/vendor/github.com/moby/buildkit/source/gitidentifier.go +++ b/vendor/github.com/moby/buildkit/source/gitidentifier.go @@ -47,9 +47,6 @@ func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) { u.Fragment = "" repo.Remote = u.String() } - if sd := path.Clean(repo.Subdir); sd == "/" || sd == "." { - repo.Subdir = "" - } return &repo, nil } @@ -72,5 +69,7 @@ func getRefAndSubdir(fragment string) (ref string, subdir string) { if len(refAndDir) > 1 && len(refAndDir[1]) != 0 { subdir = refAndDir[1] } + subdir = path.Join("/", subdir) + subdir = strings.TrimPrefix(subdir, "/") return } -- 2.54.0 ++++++ 0020-CVE-2026-33747-Fix-executor-validate-container-IDs-c.patch ++++++ >From 02584cec9d94e599bdf39c4339cbfcec5c1651cd Mon Sep 17 00:00:00 2001 From: rcmadhankumar <[email protected]> Date: Wed, 22 Apr 2026 11:31:55 +0530 Subject: [PATCH 2/2] CVE-2026-33747: Fix: executor: validate container IDs centrally -- CVE-2026-33747 BuildKit is a toolkit for converting source code to build artifacts in an efficient, expressive and repeatable manner. Prior to version 0.28.1, when using a custom BuildKit frontend, the frontend can craft an API message that causes files to be written outside of the BuildKit state directory for the execution context. The issue has been fixed in v0.28.1. The vulnerability requires using an untrusted BuildKit frontend set with `#syntax` or `--build-arg BUILDKIT_SYNTAX`. Using these options with a well-known frontend image like `docker/dockerfile` is not affected. Fix: executor: validate container IDs centrally Add executor.ValidContainerID and enforce it in runc/containerd Run paths. Only runc executor used the ID in filesystem operations. Signed-off-by: Tonis Tiigi <[email protected]> (cherry picked from commit 789df2422341960b7549d14ea475add43e73cd74) (cherry picked from commit 5e285127899ea49bad2437f2d53114bbe30dd36f) Reference: https://github.com/moby/buildkit/commit/099cf80f5ebc935c48d2925499bffe703a54cff4 Fixes CVE-2026-33747 Fixes bsc#1260967 --- .../executor/containerdexecutor/executor.go | 3 ++ .../moby/buildkit/executor/containerid.go | 18 ++++++++++ .../buildkit/executor/containerid_test.go | 33 +++++++++++++++++++ .../executor/runcexecutor/executor.go | 10 ++++-- 4 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 vendor/github.com/moby/buildkit/executor/containerid.go create mode 100644 vendor/github.com/moby/buildkit/executor/containerid_test.go diff --git a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go index ac195c4315..f5aa152c20 100644 --- a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go +++ b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go @@ -82,6 +82,9 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M if id == "" { id = identity.NewID() } + if err := executor.ValidContainerID(id); err != nil { + return err + } startedOnce := sync.Once{} done := make(chan error, 1) diff --git a/vendor/github.com/moby/buildkit/executor/containerid.go b/vendor/github.com/moby/buildkit/executor/containerid.go new file mode 100644 index 0000000000..421c8ad4eb --- /dev/null +++ b/vendor/github.com/moby/buildkit/executor/containerid.go @@ -0,0 +1,18 @@ +package executor + +import "github.com/pkg/errors" + +// ValidContainerID validates that id is non-empty and contains only ASCII letters and digits. +func ValidContainerID(id string) error { + if id == "" { + return errors.New("container id must not be empty") + } + for i := 0; i < len(id); i++ { + ch := id[i] + if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') { + continue + } + return errors.Errorf("invalid container id %q: only letters and numbers are allowed", id) + } + return nil +} diff --git a/vendor/github.com/moby/buildkit/executor/containerid_test.go b/vendor/github.com/moby/buildkit/executor/containerid_test.go new file mode 100644 index 0000000000..8912238d20 --- /dev/null +++ b/vendor/github.com/moby/buildkit/executor/containerid_test.go @@ -0,0 +1,33 @@ +package executor + +import "testing" + +func TestValidContainerID(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + id string + wantErr bool + }{ + {name: "lowercase", id: "abc123", wantErr: false}, + {name: "uppercase", id: "AbC123", wantErr: false}, + {name: "empty", id: "", wantErr: true}, + {name: "dash", id: "abc-123", wantErr: true}, + {name: "slash", id: "abc/123", wantErr: true}, + {name: "underscore", id: "abc_123", wantErr: true}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + err := ValidContainerID(tc.id) + if tc.wantErr && err == nil { + t.Fatalf("expected an error for id %q", tc.id) + } + if !tc.wantErr && err != nil { + t.Fatalf("expected no error for id %q, got %v", tc.id, err) + } + }) + } +} diff --git a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go index 213ebb7366..5a318abf72 100644 --- a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go +++ b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go @@ -140,6 +140,13 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex } func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) { + if id == "" { + id = identity.NewID() + } + if err := executor.ValidContainerID(id); err != nil { + return err + } + meta := process.Meta startedOnce := sync.Once{} @@ -200,9 +207,6 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount, defer release() } - if id == "" { - id = identity.NewID() - } bundle := filepath.Join(w.root, id) if err := os.Mkdir(bundle, 0711); err != nil { -- 2.54.0 ++++++ 0021-CVE-2026-33997-fix-for-Privilege-validation-bypass-d.patch ++++++ >From 370e3834b3e993773c0a564c014a4a0ba17d0df9 Mon Sep 17 00:00:00 2001 From: rcmadhankumar <[email protected]> Date: Wed, 27 May 2026 11:53:01 +0530 Subject: [PATCH 1/2] CVE-2026-33997: fix for Privilege validation bypass during plugin installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- CVE-2026-33997 Moby is an open source container framework. Prior to version 29.3.1, a security vulnerability has been detected that allows plugins privilege validation to be bypassed during docker plugin install. Due to an error in the daemon's privilege comparison logic, the daemon may incorrectly accept a privilege set that differs from the one approved by the user. Plugins that request exactly one privilege are also affected, because no comparison is performed at all. This issue has been patched in version 29.3.1. Fix: plugin: Fix off-by-one in privilege validation Fix an off-by-one error in isEqual() where the comparison loop started at index 1 instead of 0, causing the first privilege (after sorting alphabetically by name) to never be validated. This allowed a malicious plugin to request different values for whichever privilege sorts first — most notably "allow-all-devices", which grants unrestricted rwm access to all host devices. The bug also meant that plugins requesting exactly one privilege had zero iterations of the comparison loop, bypassing validation entirely. Also fix an existing test case ("diff-order-but-same-value") that only passed due to the off-by-one bug, and add test cases for single-element and first-sorted-element mismatches. Signed-off-by: Paweł Gronowski <[email protected]> (cherry picked from commit https://github.com/moby/moby/commit/99a095ecf04e8849318f2811bb3f687905eab09b) reference: https://github.com/advisories/GHSA-pxq6-2prw-chj9 Fixes CVE-2026-33997 Fixes bsc#1265907 --- plugin/manager.go | 50 +++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/plugin/manager.go b/plugin/manager.go index fc0eba04ee..e09f9776f3 100644 --- a/plugin/manager.go +++ b/plugin/manager.go @@ -1,14 +1,14 @@ package plugin // import "github.com/docker/docker/plugin" import ( + "cmp" "context" "encoding/json" "io" "os" "path/filepath" - "reflect" "regexp" - "sort" + "slices" "strings" "sync" "syscall" @@ -319,34 +319,42 @@ func makeLoggerStreams(id string) (stdout, stderr io.WriteCloser) { } func validatePrivileges(requiredPrivileges, privileges types.PluginPrivileges) error { - if !isEqual(requiredPrivileges, privileges, isEqualPrivilege) { + if len(requiredPrivileges) != len(privileges) { return errors.New("incorrect privileges") } - return nil -} - -func isEqual(arrOne, arrOther types.PluginPrivileges, compare func(x, y types.PluginPrivilege) bool) bool { - if len(arrOne) != len(arrOther) { - return false - } - - sort.Sort(arrOne) - sort.Sort(arrOther) + a := normalizePrivileges(requiredPrivileges) + b := normalizePrivileges(privileges) - for i := 1; i < arrOne.Len(); i++ { - if !compare(arrOne[i], arrOther[i]) { - return false + for i := range a { + if a[i].Name != b[i].Name { + return errors.New("incorrect privileges") + } + if !slices.Equal(a[i].Value, b[i].Value) { + return errors.New("incorrect privileges") } } - return true + return nil } -func isEqualPrivilege(a, b types.PluginPrivilege) bool { - if a.Name != b.Name { - return false +// normalizePrivileges returns a normalized copy of privileges with privilege names +// and each privilege's values sorted for order-insensitive comparison. +// The input is not mutated. +func normalizePrivileges(privileges types.PluginPrivileges) types.PluginPrivileges { + normalized := make(types.PluginPrivileges, len(privileges)) + for i, privilege := range privileges { + normalized[i] = types.PluginPrivilege{ + Name: privilege.Name, + Description: privilege.Description, + Value: slices.Clone(privilege.Value), + } + slices.Sort(normalized[i].Value) } - return reflect.DeepEqual(a.Value, b.Value) + slices.SortFunc(normalized, func(a, b types.PluginPrivilege) int { + return cmp.Compare(a.Name, b.Name) + }) + + return normalized } -- 2.54.0 ++++++ 0022-CVE-2026-34040-fix-for-Authz-zero-length-regression.patch ++++++ >From c0db0be1b3e4682eefb1aeb597ae58745ffba7f0 Mon Sep 17 00:00:00 2001 From: rcmadhankumar <[email protected]> Date: Wed, 27 May 2026 12:11:51 +0530 Subject: [PATCH 2/2] CVE-2026-34040: fix for Authz zero length regression -- MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CVE-2026-34040 Moby is an open source container framework. Prior to version 29.3.1, a security vulnerability has been detected that allows attackers to bypass authorization plugins (AuthZ). This issue has been patched in version 29.3.1. Fix: pkg/authz: Reject requests with body size exceeding 4 MiB Thanks to Paweł Gronowski <[email protected]> cherry pick of (https://github.com/moby/moby/commit/e89edb19ad7de0407a5d31e3111cb01aa10b5a38) Fixes CVE-2026-34040 Fixes bsc#1265929 Ref: https://github.com/advisories/GHSA-x744-4wpc-v9h2 --- pkg/authorization/authz.go | 58 ++++++++++++++------------------------ 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/pkg/authorization/authz.go b/pkg/authorization/authz.go index 68ed8bbdaf..b58b4850f0 100644 --- a/pkg/authorization/authz.go +++ b/pkg/authorization/authz.go @@ -15,7 +15,7 @@ import ( "github.com/sirupsen/logrus" ) -const maxBodySize = 1048576 // 1MB +const maxBodySize = 4 * 1024 * 1024 // 4MiB // NewCtx creates new authZ context, it is used to store authorization information related to a specific docker // REST http session @@ -54,28 +54,31 @@ type Ctx struct { authReq *Request } -func isChunked(r *http.Request) bool { - // RFC 7230 specifies that content length is to be ignored if Transfer-Encoding is chunked - if strings.EqualFold(r.Header.Get("Transfer-Encoding"), "chunked") { - return true - } - for _, v := range r.TransferEncoding { - if strings.EqualFold(v, "chunked") { - return true - } - } - return false -} - // AuthZRequest authorized the request to the docker daemon using authZ plugins func (ctx *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error { var body []byte - if sendBody(ctx.requestURI, r.Header) && (r.ContentLength > 0 || isChunked(r)) && r.ContentLength < maxBodySize { - var err error - body, r.Body, err = drainBody(r.Body) - if err != nil { + if sendBody(ctx.requestURI, r.Header) { + // Wrap the original request body in a buffered reader so we can inspect + // the prefix without consuming bytes from the downstream reader. + // `Peek(maxBodySize + 1)` is used as a size check: + // - err == nil means at least maxBodySize+1 bytes are buffered/available, + // so the payload exceeds the plugin limit and is rejected. + // - otherwise, `peeked` contains the complete body bytes currently available + // (for short bodies this is the full payload), and reads from r.Body still + // stream the original body unchanged. + bufBody := bufio.NewReaderSize(r.Body, maxBodySize+1) + r.Body = ioutils.NewReadCloserWrapper(bufBody, r.Body.Close) + + peeked, err := bufBody.Peek(maxBodySize + 1) + if err == nil { + // Successfully peeked maxBodySize+1 bytes, so body is too large + // TODO: Allows plugin to opt in + return fmt.Errorf("request body too large for authorization plugin: size exceeds %d bytes", maxBodySize) + } else if err != io.EOF { return err } + + body = peeked } var h bytes.Buffer @@ -141,25 +144,6 @@ func (ctx *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error { return nil } -// drainBody dump the body (if its length is less than 1MB) without modifying the request state -func drainBody(body io.ReadCloser) ([]byte, io.ReadCloser, error) { - bufReader := bufio.NewReaderSize(body, maxBodySize) - newBody := ioutils.NewReadCloserWrapper(bufReader, func() error { return body.Close() }) - - data, err := bufReader.Peek(maxBodySize) - // Body size exceeds max body size - if err == nil { - logrus.Warnf("Request body is larger than: '%d' skipping body", maxBodySize) - return nil, newBody, nil - } - // Body size is less than maximum size - if err == io.EOF { - return data, newBody, nil - } - // Unknown error - return nil, newBody, err -} - func isAuthEndpoint(urlPath string) (bool, error) { // eg www.test.com/v1.24/auth/optional?optional1=something&optional2=something (version optional) matched, err := regexp.MatchString(`^[^\/]*\/(v\d[\d\.]*\/)?auth.*`, urlPath) -- 2.54.0 ++++++ 0023-CVE-2026-33186-grpc-enforce-strict-path-checking-for.patch ++++++ >From a1d805833aa83220f0177446ef73bc849fd1dea3 Mon Sep 17 00:00:00 2001 From: rcmadhankumar <[email protected]> Date: Tue, 9 Jun 2026 12:52:32 +0530 Subject: [PATCH 1/4] CVE-2026-33186: grpc: enforce strict path checking for incoming requests on the server -- CVE-2026-33186 gRPC-Go is the Go language implementation of gRPC. Versions prior to 1.79.3 have an authorization bypass resulting from improper input validation of the HTTP/2 `:path` pseudo-header. The gRPC-Go server was too lenient in its routing logic, accepting requests where the `:path` omitted the mandatory leading slash (e.g., `Service/Method` instead of `/Service/Method`). While the server successfully routed these requests to the correct handler, authorization interceptors (including the official `grpc/authz` package) evaluated the raw, non-canonical path string. Consequently, "deny" rules defined using canonical paths (starting with `/`) failed to match the incoming request, allowing it to bypass the policy if a fallback "allow" rule was present. This affects gRPC-Go servers that use path-based authorization interceptors, such as the official RBAC implementation in `google.golang.org/grpc/authz` or custom interceptors relying on `info.FullMethod` or `grpc.Method(ctx)`; AND that have a security policy contains specific "deny" rules for canonical paths but allows other requests by default (a fallback "allow" rule). The vulnerability is exploitable by an attacker who can send raw HTTP/2 frames with malformed `:path` headers directly to the gRPC server. The fix in version 1.79.3 ensures that any request with a `:path` that does not start with a leading slash is immediately rejected with a `codes.Unimplemented` error, preventing it from reaching authorization interceptors or handlers with a non-canonical path string. While upgrading is the most secure and recommended path, users can mitigate the vulnerability using one of the following methods: Use a validating interceptor (recommended mitigation); infrastructure-level normalization; and/or policy hardening. Ref: https://github.com/grpc/grpc-go/security/advisories/GHSA-p77j-4mvh-x3m3 Fix: grpc: enforce strict path checking for incoming requests on the server (#8981) RELEASE NOTES: * server: fix an authorization bypass where malformed :path headers (missing the leading slash) could bypass path-based restricted "deny" rules in interceptors like `grpc/authz`. Any request with a non-canonical path is now immediately rejected with an `Unimplemented` error. This is a backport of <https://github.com/grpc/grpc-go/commit/72186f163e75a065c39e6f7df9b6dea07fbdeff5> Fixes CVE-2026-33186 Fixes bsc#1260279 --- .../grpc/internal/envconfig/envconfig.go | 25 ++++++++ vendor/google.golang.org/grpc/server.go | 57 +++++++++++++------ 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go index 6f02725431..4cb283a246 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go @@ -32,4 +32,29 @@ const ( var ( // TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false"). TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false") + + // DisableStrictPathChecking indicates whether strict path checking is + // disabled. This feature can be disabled by setting the environment + // variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING to "true". + // + // When strict path checking is enabled, gRPC will reject requests with + // paths that do not conform to the gRPC over HTTP/2 specification found at + // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md. + // + // When disabled, gRPC will allow paths that do not contain a leading slash. + // Enabling strict path checking is recommended for security reasons, as it + // prevents potential path traversal vulnerabilities. + // + // A future release will remove this environment variable, enabling strict + // path checking behavior unconditionally. + DisableStrictPathChecking = boolFromEnv("GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING", false) ) + +func boolFromEnv(envVar string, def bool) bool { + if def { + // The default is true; return true unless the variable is "false". + return !strings.EqualFold(os.Getenv(envVar), "false") + } + // The default is false; return false unless the variable is "true". + return strings.EqualFold(os.Getenv(envVar), "true") +} diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index f4dde72b41..145afb2dee 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -43,6 +43,7 @@ import ( "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/binarylog" "google.golang.org/grpc/internal/channelz" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/grpcrand" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/transport" @@ -146,6 +147,8 @@ type Server struct { czData *channelzData serverWorkerChannels []chan *serverWorkerData + + strictPathCheckingLogEmitted sync.Once } type serverOptions struct { @@ -1680,28 +1683,50 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp return err } +func (s *Server) handleMalformedMethodName(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"Malformed method name %q", []interface{}{stream.Method()}}, true) + trInfo.tr.SetError() + } + errDesc := fmt.Sprintf("malformed method name: %q", stream.Method()) + if err := t.WriteStatus(stream, status.New(codes.Unimplemented, errDesc)); err != nil { + if trInfo != nil { + trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) + trInfo.tr.SetError() + } + channelz.Warningf(logger, s.channelzID, "grpc: Server.handleStream failed to write status: %v", err) + } + if trInfo != nil { + trInfo.tr.Finish() + } +} + func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { sm := stream.Method() - if sm != "" && sm[0] == '/' { + if sm == "" { + s.handleMalformedMethodName(t, stream, trInfo) + return + } + if sm[0] != '/' { + // TODO(easwars): Add a link to the CVE in the below log messages once + // published. + if envconfig.DisableStrictPathChecking { + s.strictPathCheckingLogEmitted.Do(func() { + channelz.Warningf(logger, s.channelzID, "grpc: Server.handleStream received malformed method name %q. Allowing it because the environment variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING is set to true, but this option will be removed in a future release.", sm) + }) + } else { + s.strictPathCheckingLogEmitted.Do(func() { + channelz.Warningf(logger, s.channelzID, "grpc: Server.handleStream rejected malformed method name %q. To temporarily allow such requests, set the environment variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING to true. Note that this is not recommended as it may allow requests to bypass security policies.", sm) + }) + s.handleMalformedMethodName(t, stream, trInfo) + return + } + } else { sm = sm[1:] } pos := strings.LastIndex(sm, "/") if pos == -1 { - if trInfo != nil { - trInfo.tr.LazyLog(&fmtStringer{"Malformed method name %q", []interface{}{sm}}, true) - trInfo.tr.SetError() - } - errDesc := fmt.Sprintf("malformed method name: %q", stream.Method()) - if err := t.WriteStatus(stream, status.New(codes.Unimplemented, errDesc)); err != nil { - if trInfo != nil { - trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) - trInfo.tr.SetError() - } - channelz.Warningf(logger, s.channelzID, "grpc: Server.handleStream failed to write status: %v", err) - } - if trInfo != nil { - trInfo.tr.Finish() - } + s.handleMalformedMethodName(t, stream, trInfo) return } service := sm[:pos] -- 2.54.0 ++++++ 0024-CVE-2026-33814-http2-prevent-hanging-Transport-due-t.patch ++++++ >From 8e99acd3a2aee8188e765aca0b44f1f3302f6be9 Mon Sep 17 00:00:00 2001 From: rcmadhankumar <[email protected]> Date: Tue, 9 Jun 2026 13:12:16 +0530 Subject: [PATCH 2/4] CVE-2026-33814: http2: prevent hanging Transport due to bad SETTINGS frame -- CVE-2026-33814 When processing HTTP/2 SETTINGS frames, transport will enter an infinite loop of writing CONTINUATION frames if it receives a SETTINGS_MAX_FRAME_SIZE with a value of 0. Fix: http2: prevent hanging Transport due to bad SETTINGS frame This CL backports https://go.dev/cl/761581 to x/net. Change-Id: Ied435a51fdd8664d41dae14d082c39c76a6a6964 Reviewed-on: https://go-review.googlesource.com/c/net/+/761640 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Nicholas Husin <[email protected]> Reviewed-by: Damien Neil <[email protected]> Fixes bsc#1265782 Fixes golang/go#78476 Fixes CVE-2026-33814 Backport of <https://github.com/golang/net/commit/1e71bd86e4a302b4e731bc06da6eb51679c7bd49> --- vendor/golang.org/x/net/http2/transport.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 4515b22c4a..811324fa46 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -2843,6 +2843,9 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { var seenMaxConcurrentStreams bool err := f.ForeachSetting(func(s Setting) error { + if err := s.Valid(); err != nil { + return err + } switch s.ID { case SettingMaxFrameSize: cc.maxFrameSize = s.Val -- 2.54.0 ++++++ 0025-CVE-2026-39821-idna-update-from-x-text-fix-ToUnicode.patch ++++++ ++++ 30086 lines (skipped) ++++++ 0026-CVE-2026-41567-daemon-Decompress-archives-before-ent.patch ++++++ >From 7a43405a79537f803ce747551fee457fbda11475 Mon Sep 17 00:00:00 2001 From: rcmadhankumar <[email protected]> Date: Tue, 9 Jun 2026 15:40:00 +0530 Subject: [PATCH 4/4] CVE-2026-41567: daemon: Decompress archives before entering container filesystem -- MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CVE-2026-41567 Moby is an open source container framework. In versions prior to 29.5.1 and in moby/moby v2 prior to v2.0.0-beta.14, when a compressed archive is uploaded to a container via `PUT /containers/{id}/archive` or piped through `docker cp -`, the daemon resolves decompression binaries (such as `xz` or `unpigz`) from the container's filesystem rather than the host's due to incorrect ordering of operations. A malicious container image containing a trojanized decompression binary can achieve arbitrary code execution with full daemon privileges, including host root UID and unrestricted capabilities, when a user uploads a compressed (xz or gzip) archive into that container. This issue is fixed in Docker Engine 29.5.1 and moby/moby v2.0.0-beta.14. Workarounds include only running containers from trusted images, using authorization plugins to restrict access to the `PUT /containers/{id}/archive` endpoint, and avoiding piping compressed archives into containers created from untrusted images Fix: daemon: Decompress archives before entering container filesystem Move decompression outside RunInFS to prevent executing attacker-controlled binaries from within the container filesystem. When dockerd handles `PUT /containers/{id}/archive`, it switches root into the container's filesystem before extracting the archive. Previously, archive.Untar was called inside RunInFS, which meant decompression binaries (xz, unpigz) were resolved via PATH inside the container's filesystem. A malicious binary at /usr/bin/xz in the container would be executed as host root. Fix by calling decompressing the archive before entering the container filesystem, then using unpacking the uncompressed tar stream inside RunInFS. This ensures decompression binaries are always resolved from the host filesystem. Signed-off-by: Paweł Gronowski <[email protected]> Fixes bsc#1267827 Fixes CVE-2026-41567 Backport of <https://github.com/moby/moby/commit/2022313ffe5a8c04890b5295bc52670ee6df8070? Ref: https://github.com/moby/moby/commit/06224f7ad000fda8de7939ea08aa61ad9814ee63 Ref: https://github.com/advisories/GHSA-x86f-5xw2-fm2r --- daemon/archive_unix.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/daemon/archive_unix.go b/daemon/archive_unix.go index 3098dbeadf..155a7d2968 100644 --- a/daemon/archive_unix.go +++ b/daemon/archive_unix.go @@ -101,6 +101,15 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path container.Lock() defer container.Unlock() + // Decompress the archive before switching into the container's + // filesystem to avoid executing decompression binaries (xz, unpigz) + // that may have been placed inside the container image. + decompressed, err := archive.DecompressStream(content) + if err != nil { + return err + } + defer decompressed.Close() + cfs, err := daemon.openContainerFS(container) if err != nil { return err @@ -150,7 +159,7 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path } } - return archive.Untar(content, absPath, options) + return archive.UntarUncompressed(decompressed, absPath, options) }) if err != nil { return err -- 2.54.0
