CVE-2022-1708
Description
A vulnerability was found in CRI-O that causes memory or disk space exhaustion on the node for anyone with access to the Kube API. The ExecSync request runs commands in a container and logs the output of the command. This output is then read by CRI-O after command execution, and it is read in a manner where the entire file corresponding to the output of the command is read in. Thus, if the output of the command is large it is possible to exhaust the memory or the disk space of the node when CRI-O reads the output of the command. The highest threat from this vulnerability is system availability.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CRI-O vulnerability allows node resource exhaustion via large ExecSync command output, leading to denial of service.
A vulnerability in CRI-O, an Open Container Initiative-based implementation of the Kubernetes Container Runtime Interface, allows an attacker with access to the Kubernetes API to cause memory or disk space exhaustion on the node [1][2][4]. The issue arises from the ExecSync request, which runs a command in a container and logs its output. CRI-O reads the entire output file after command execution without size limits, enabling resource exhaustion if the output is large [2][4].
An attacker can exploit this by sending an ExecSync request that generates a large amount of output. For example, a simple command that outputs repeated characters can produce gigabytes of data, which is written to disk by conmon and then read by CRI-O [4]. The attack requires only access to the Kubernetes API, as no additional authentication is needed beyond that for making ExecSync calls. This is a low-complexity attack that can be executed from within a pod with appropriate permissions [2].
The impact is a denial of service on the node. Memory and disk usage from the output are not attributed to the container, so other containers and services on the node may be unable to allocate resources, causing system unavailability [4]. The highest threat is to system availability, with no impact on confidentiality or integrity [2].
CRI-O has released patches for this vulnerability in versions 1.24.1, 1.23.3, 1.22.5, 1.21.8, 1.20.8, and 1.19.7 [4]. At the time of disclosure, no workaround exists other than ensuring only trusted images are used [4]. Users should update to a patched version as soon as possible.
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/cri-o/cri-oGo | >= 1.24.0, < 1.24.1 | 1.24.1 |
github.com/cri-o/cri-oGo | >= 1.23.0, < 1.23.3 | 1.23.3 |
github.com/cri-o/cri-oGo | < 1.22.5 | 1.22.5 |
Affected products
63- CRI-O/CRI-Odescription
- ghsa-coords62 versionspkg:golang/github.com/cri-o/cri-opkg:rpm/almalinux/aardvark-dnspkg:rpm/almalinux/buildahpkg:rpm/almalinux/buildah-testspkg:rpm/almalinux/cockpit-podmanpkg:rpm/almalinux/conmonpkg:rpm/almalinux/containernetworking-pluginspkg:rpm/almalinux/containers-commonpkg:rpm/almalinux/container-selinuxpkg:rpm/almalinux/critpkg:rpm/almalinux/criupkg:rpm/almalinux/criu-develpkg:rpm/almalinux/criu-libspkg:rpm/almalinux/crunpkg:rpm/almalinux/fuse-overlayfspkg:rpm/almalinux/libslirppkg:rpm/almalinux/libslirp-develpkg:rpm/almalinux/netavarkpkg:rpm/almalinux/oci-seccomp-bpf-hookpkg:rpm/almalinux/podmanpkg:rpm/almalinux/podman-catatonitpkg:rpm/almalinux/podman-dockerpkg:rpm/almalinux/podman-gvproxypkg:rpm/almalinux/podman-pluginspkg:rpm/almalinux/podman-remotepkg:rpm/almalinux/podman-testspkg:rpm/almalinux/python3-criupkg:rpm/almalinux/python3-podmanpkg:rpm/almalinux/runcpkg:rpm/almalinux/skopeopkg:rpm/almalinux/skopeo-testspkg:rpm/almalinux/slirp4netnspkg:rpm/almalinux/toolboxpkg:rpm/almalinux/toolbox-testspkg:rpm/almalinux/udicapkg:rpm/opensuse/conmon&distro=openSUSE%20Leap%2015.3pkg:rpm/opensuse/conmon&distro=openSUSE%20Leap%2015.4pkg:rpm/opensuse/conmon&distro=openSUSE%20Leap%20Micro%205.2pkg:rpm/opensuse/conmon&distro=openSUSE%20Leap%20Micro%205.3pkg:rpm/opensuse/conmon&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/cri-o&distro=openSUSE%20Tumbleweedpkg:rpm/suse/conmon&distro=SUSE%20Enterprise%20Storage%206pkg:rpm/suse/conmon&distro=SUSE%20Enterprise%20Storage%207pkg:rpm/suse/conmon&distro=SUSE%20Enterprise%20Storage%207.1pkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP1-ESPOSpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP1-LTSSpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP2-ESPOSpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP2-LTSSpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Micro%205.1pkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Micro%205.2pkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Micro%205.3pkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP3pkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP4pkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP1-BCLpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP1-LTSSpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP2-BCLpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP2-LTSSpkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP1pkg:rpm/suse/conmon&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP2pkg:rpm/suse/conmon&distro=SUSE%20Manager%20Proxy%204.1pkg:rpm/suse/conmon&distro=SUSE%20Manager%20Retail%20Branch%20Server%204.1pkg:rpm/suse/conmon&distro=SUSE%20Manager%20Server%204.1
>= 1.24.0, < 1.24.1+ 61 more
- (no CPE)range: >= 1.24.0, < 1.24.1
- (no CPE)range: < 2:1.0.1-35.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 1:1.24.5-2.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 1:1.24.5-2.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 46-1.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:2.1.4-1.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 1:1.1.1-2.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:1-35.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:2.189.0-1.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 3.15-3.module_el8.6.0+3137+d33c3efb
- (no CPE)range: < 3.15-3.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 3.15-3.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 3.15-3.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 1.5-1.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 1.9-1.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 4.4.0-1.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 4.4.0-1.module_el8.6.0+3137+d33c3efb
- (no CPE)range: < 2:1.0.1-35.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 1.2.5-1.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:4.0.2-8.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:4.0.2-8.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:4.0.2-8.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:4.0.2-8.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:4.0.2-8.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:4.0.2-8.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:4.0.2-8.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 3.15-3.module_el8.6.0+3137+d33c3efb
- (no CPE)range: < 4.0.0-1.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 1:1.1.4-1.module_el8.7.0+3344+484dae7b
- (no CPE)range: < 2:1.6.2-5.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:1.6.2-5.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 1.1.8-2.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 0.0.99.3-0.5.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 0.0.99.3-0.5.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 0.2.6-3.module_el8.6.0+2886+d33c3efb
- (no CPE)range: < 2.1.5-150300.8.6.1
- (no CPE)range: < 2.1.5-150400.3.3.1
- (no CPE)range: < 2.1.5-150300.8.6.1
- (no CPE)range: < 2.1.5-150400.3.3.1
- (no CPE)range: < 2.1.2-1.1
- (no CPE)range: < 1.24.1-1.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.5-150300.8.6.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.5-150300.8.6.1
- (no CPE)range: < 2.1.5-150300.8.6.1
- (no CPE)range: < 2.1.5-150400.3.3.1
- (no CPE)range: < 2.1.5-150300.8.6.1
- (no CPE)range: < 2.1.5-150400.3.3.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
- (no CPE)range: < 2.1.3-150100.3.9.1
Patches
1f032cf649eccMerge pull request from GHSA-fcm2-6c3h-pg6j
10 files changed · +282 −7
internal/config/conmonmgr/conmonmgr.go+29 −3 modified@@ -1,6 +1,7 @@ package conmonmgr import ( + "bytes" "path" "strings" @@ -10,11 +11,15 @@ import ( "github.com/sirupsen/logrus" ) -var versionSupportsSync = semver.MustParse("2.0.19") +var ( + versionSupportsSync = semver.MustParse("2.0.19") + versionSupportsLogGlobalSizeMax = semver.MustParse("2.1.2") +) type ConmonManager struct { - conmonVersion *semver.Version - supportsSync bool + conmonVersion *semver.Version + supportsSync bool + supportsLogGlobalSizeMax bool } // this function is heavily based on github.com/containers/common#probeConmon @@ -37,6 +42,7 @@ func New(conmonPath string) (*ConmonManager, error) { } c.initializeSupportsSync() + c.initializeSupportsLogGlobalSizeMax(conmonPath) return c, nil } @@ -49,6 +55,26 @@ func (c *ConmonManager) parseConmonVersion(versionString string) error { return nil } +func (c *ConmonManager) initializeSupportsLogGlobalSizeMax(conmonPath string) { + c.supportsLogGlobalSizeMax = c.conmonVersion.GTE(versionSupportsLogGlobalSizeMax) + if !c.supportsLogGlobalSizeMax { + // Read help output as a fallback in case the feature was backported to conmon, + // but the version wasn't bumped. + helpOutput, err := cmdrunner.CombinedOutput(conmonPath, "--help") + c.supportsLogGlobalSizeMax = err == nil && bytes.Contains(helpOutput, []byte("--log-global-size-max")) + } + verb := "does not" + if c.supportsLogGlobalSizeMax { + verb = "does" + } + + logrus.Infof("Conmon %s support the --log-global-size-max option", verb) +} + +func (c *ConmonManager) SupportsLogGlobalSizeMax() bool { + return c.supportsLogGlobalSizeMax +} + func (c *ConmonManager) initializeSupportsSync() { c.supportsSync = c.conmonVersion.GTE(versionSupportsSync) verb := "does not"
internal/config/conmonmgr/conmonmgr_test.go+105 −1 modified@@ -70,7 +70,7 @@ var _ = t.Describe("ConmonManager", func() { It("should succeed when output expected", func() { // Given gomock.InOrder( - runner.EXPECT().CombinedOutput(gomock.Any(), gomock.Any()).Return([]byte("conmon version 2.0.0"), nil), + runner.EXPECT().CombinedOutput(gomock.Any(), gomock.Any()).Return([]byte("conmon version 2.2.2"), nil), ) // When @@ -170,4 +170,108 @@ var _ = t.Describe("ConmonManager", func() { Expect(mgr.SupportsSync()).To(Equal(true)) }) }) + t.Describe("initializeSupportsLogGlobalSizeMax", func() { + var mgr *ConmonManager + BeforeEach(func() { + runner = runnerMock.NewMockCommandRunner(mockCtrl) + cmdrunner.SetMocked(runner) + mgr = new(ConmonManager) + }) + It("should be false when major version less", func() { + // Given + gomock.InOrder( + runner.EXPECT().CombinedOutput(gomock.Any(), gomock.Any()).Return([]byte{}, errors.New("cmd failed")), + ) + err := mgr.parseConmonVersion("1.1.2") + Expect(err).To(BeNil()) + // When + mgr.initializeSupportsLogGlobalSizeMax("") + + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(false)) + }) + It("should be true when major version greater", func() { + // Given + err := mgr.parseConmonVersion("3.1.1") + Expect(err).To(BeNil()) + + // When + mgr.initializeSupportsLogGlobalSizeMax("") + + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(true)) + }) + It("should be false when minor version less", func() { + // Given + gomock.InOrder( + runner.EXPECT().CombinedOutput(gomock.Any(), gomock.Any()).Return([]byte{}, errors.New("cmd failed")), + ) + err := mgr.parseConmonVersion("2.0.2") + Expect(err).To(BeNil()) + // When + mgr.initializeSupportsLogGlobalSizeMax("") + + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(false)) + }) + It("should be true when minor version greater", func() { + // Given + err := mgr.parseConmonVersion("2.2.2") + Expect(err).To(BeNil()) + + // When + mgr.initializeSupportsLogGlobalSizeMax("") + + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(true)) + }) + It("should be false when patch version less", func() { + // Given + gomock.InOrder( + runner.EXPECT().CombinedOutput(gomock.Any(), gomock.Any()).Return([]byte{}, errors.New("cmd failed")), + ) + err := mgr.parseConmonVersion("2.1.1") + Expect(err).To(BeNil()) + // When + mgr.initializeSupportsLogGlobalSizeMax("") + + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(false)) + }) + It("should be true when patch version greater", func() { + // Given + err := mgr.parseConmonVersion("2.1.3") + Expect(err).To(BeNil()) + + // When + mgr.initializeSupportsLogGlobalSizeMax("") + + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(true)) + }) + It("should be true when version equal", func() { + // Given + err := mgr.parseConmonVersion("2.1.2") + Expect(err).To(BeNil()) + + // When + mgr.initializeSupportsLogGlobalSizeMax("") + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(true)) + }) + It("should be true if feature backported", func() { + // Given + gomock.InOrder( + runner.EXPECT().CombinedOutput(gomock.Any(), gomock.Any()).Return([]byte("--log-global-size-max"), nil), + ) + err := mgr.parseConmonVersion("0.0.0") + Expect(err).To(BeNil()) + + // When + mgr.initializeSupportsLogGlobalSizeMax("") + + // Then + Expect(mgr.SupportsLogGlobalSizeMax()).To(Equal(true)) + }) + }) })
internal/oci/oci.go+5 −0 modified@@ -35,6 +35,11 @@ const ( // killContainerTimeout is the timeout that we wait for the container to // be SIGKILLed. killContainerTimeout = 2 * time.Minute + + // maxExecSyncSize is the maximum size of exec sync output CRI-O will process. + // It is set to the amount of logs allowed in the dockershim implementation: + // https://github.com/kubernetes/kubernetes/pull/82514 + maxExecSyncSize = 16 * 1024 * 1024 ) // Runtime is the generic structure holding both global and specific
internal/oci/runtime_oci.go+18 −1 modified@@ -486,6 +486,9 @@ func (r *runtimeOCI) ExecSyncContainer(ctx context.Context, c *Container, comman if r.config.ConmonSupportsSync() { args = append(args, "--sync") } + if r.config.ConmonSupportsLogGlobalSizeMax() { + args = append(args, "--log-global-size-max", strconv.Itoa(maxExecSyncSize)) + } if c.terminal { args = append(args, "-t") } @@ -661,7 +664,7 @@ func (r *runtimeOCI) ExecSyncContainer(ctx context.Context, c *Container, comman // ExecSyncResponse we have to read the logfile. // XXX: Currently runC dups the same console over both stdout and stderr, // so we can't differentiate between the two. - logBytes, err := ioutil.ReadFile(logPath) + logBytes, err := TruncateAndReadFile(ctx, logPath, maxExecSyncSize) if err != nil { return nil, &ExecSyncError{ Stdout: stdoutBuf, @@ -680,6 +683,20 @@ func (r *runtimeOCI) ExecSyncContainer(ctx context.Context, c *Container, comman }, nil } +func TruncateAndReadFile(ctx context.Context, path string, size int64) ([]byte, error) { + info, err := os.Stat(path) + if err != nil { + return nil, err + } + if info.Size() > size { + log.Errorf(ctx, "Exec sync output in file %s has size %d which is longer than expected size of %d", path, info.Size(), size) + if err := os.Truncate(path, size); err != nil { + return nil, err + } + } + return os.ReadFile(path) +} + // UpdateContainer updates container resources func (r *runtimeOCI) UpdateContainer(ctx context.Context, c *Container, res *rspec.LinuxResources) error { if c.Spoofed() {
internal/oci/runtime_oci_test.go+39 −0 modified@@ -3,6 +3,7 @@ package oci_test import ( "context" "math/rand" + "os" "os/exec" "time" @@ -142,6 +143,44 @@ var _ = t.Describe("Oci", func() { }) } }) + Context("TruncateAndReadFile", func() { + tests := []struct { + title string + contents []byte + expected []byte + fail bool + size int64 + }{ + { + title: "should read file if size is smaller than limit", + contents: []byte("abcd"), + expected: []byte("abcd"), + size: 5, + }, + { + title: "should read only size if size is same as limit", + contents: []byte("abcd"), + expected: []byte("abcd"), + size: 4, + }, + { + title: "should read only size if size is larger than limit", + contents: []byte("abcd"), + expected: []byte("abc"), + size: 3, + }, + } + for _, test := range tests { + test := test + It(test.title, func() { + fileName := t.MustTempFile("to-read") + Expect(os.WriteFile(fileName, test.contents, 0o644)).To(BeNil()) + found, err := oci.TruncateAndReadFile(context.Background(), fileName, test.size) + Expect(err).To(BeNil()) + Expect(found).To(Equal(test.expected)) + }) + } + }) }) func waitContainerStopAndFailAfterTimeout(ctx context.Context,
internal/oci/runtime_vm.go+3 −2 modified@@ -39,6 +39,7 @@ import ( "k8s.io/client-go/tools/remotecommand" types "k8s.io/cri-api/pkg/apis/runtime/v1" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" + kioutil "k8s.io/kubernetes/pkg/kubelet/util/ioutils" utilexec "k8s.io/utils/exec" ) @@ -307,8 +308,8 @@ func (r *runtimeVM) ExecSyncContainer(ctx context.Context, c *Container, command defer log.Debugf(ctx, "RuntimeVM.ExecSyncContainer() end") var stdoutBuf, stderrBuf bytes.Buffer - stdout := cioutil.NewNopWriteCloser(&stdoutBuf) - stderr := cioutil.NewNopWriteCloser(&stderrBuf) + stdout := kioutil.WriteCloserWrapper(kioutil.LimitWriter(&stdoutBuf, maxExecSyncSize)) + stderr := kioutil.WriteCloserWrapper(kioutil.LimitWriter(&stderrBuf, maxExecSyncSize)) exitCode, err := r.execContainerCommon(ctx, c, command, timeout, nil, stdout, stderr, c.terminal, nil) if err != nil {
pkg/config/config.go+4 −0 modified@@ -1183,6 +1183,10 @@ func (c *RuntimeConfig) ConmonSupportsSync() bool { return c.conmonManager.SupportsSync() } +func (c *RuntimeConfig) ConmonSupportsLogGlobalSizeMax() bool { + return c.conmonManager.SupportsLogGlobalSizeMax() +} + func (c *RuntimeConfig) ValidatePinnsPath(executable string) error { var err error c.PinnsPath, err = validateExecutablePath(executable, c.PinnsPath)
test/ctr.bats+8 −0 modified@@ -514,6 +514,14 @@ function check_oci_annotation() { crictl exec --sync "$ctr_id" /bin/sh -c "[[ -t 1 ]]" } +@test "ctr execsync should cap output" { + start_crio + + ctr_id=$(crictl run "$TESTDATA"/container_sleep.json "$TESTDATA"/sandbox_config.json) + + [[ $(crictl exec --sync "$ctr_id" /bin/sh -c "for i in $(seq 1 50000000); do echo -n 'a'; done" | wc -c) -le 16777216 ]] +} + @test "ctr device add" { # In an user namespace we can only bind mount devices from the host, not mknod # https://github.com/opencontainers/runc/blob/master/libcontainer/rootfs_linux.go#L480-L481
vendor/k8s.io/kubernetes/pkg/kubelet/util/ioutils/ioutils.go+70 −0 added@@ -0,0 +1,70 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ioutils + +import "io" + +// writeCloserWrapper represents a WriteCloser whose closer operation is noop. +type writeCloserWrapper struct { + Writer io.Writer +} + +func (w *writeCloserWrapper) Write(buf []byte) (int, error) { + return w.Writer.Write(buf) +} + +func (w *writeCloserWrapper) Close() error { + return nil +} + +// WriteCloserWrapper returns a writeCloserWrapper. +func WriteCloserWrapper(w io.Writer) io.WriteCloser { + return &writeCloserWrapper{w} +} + +// LimitWriter is a copy of the standard library ioutils.LimitReader, +// applied to the writer interface. +// LimitWriter returns a Writer that writes to w +// but stops with EOF after n bytes. +// The underlying implementation is a *LimitedWriter. +func LimitWriter(w io.Writer, n int64) io.Writer { return &LimitedWriter{w, n} } + +// A LimitedWriter writes to W but limits the amount of +// data returned to just N bytes. Each call to Write +// updates N to reflect the new amount remaining. +// Write returns EOF when N <= 0 or when the underlying W returns EOF. +type LimitedWriter struct { + W io.Writer // underlying writer + N int64 // max bytes remaining +} + +func (l *LimitedWriter) Write(p []byte) (n int, err error) { + if l.N <= 0 { + return 0, io.ErrShortWrite + } + truncated := false + if int64(len(p)) > l.N { + p = p[0:l.N] + truncated = true + } + n, err = l.W.Write(p) + l.N -= int64(n) + if err == nil && truncated { + err = io.ErrShortWrite + } + return +}
vendor/modules.txt+1 −0 modified@@ -1741,6 +1741,7 @@ k8s.io/kubernetes/pkg/kubelet/cri/streaming k8s.io/kubernetes/pkg/kubelet/cri/streaming/portforward k8s.io/kubernetes/pkg/kubelet/cri/streaming/remotecommand k8s.io/kubernetes/pkg/kubelet/types +k8s.io/kubernetes/pkg/kubelet/util/ioutils k8s.io/kubernetes/pkg/proxy k8s.io/kubernetes/pkg/proxy/config k8s.io/kubernetes/pkg/proxy/healthcheck
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-fcm2-6c3h-pg6jghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-1708ghsaADVISORY
- bugzilla.redhat.com/show_bug.cgighsax_refsource_MISCWEB
- github.com/cri-o/cri-o/commit/f032cf649ecc7e0c46718bd9e7814bfb317cb544ghsax_refsource_MISCWEB
- github.com/cri-o/cri-o/security/advisories/GHSA-fcm2-6c3h-pg6jghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.