containerd supplementary groups are not set up properly
Description
containerd is an open source container runtime. A bug was found in containerd prior to versions 1.6.18 and 1.5.18 where supplementary groups are not set up properly inside a container. If an attacker has direct access to a container and manipulates their supplementary group access, they may be able to use supplementary group access to bypass primary group restrictions in some cases, potentially gaining access to sensitive information or gaining the ability to execute code in that container. Downstream applications that use the containerd client library may be affected as well.
This bug has been fixed in containerd v1.6.18 and v.1.5.18. Users should update to these versions and recreate containers to resolve this issue. Users who rely on a downstream application that uses containerd's client library should check that application for a separate advisory and instructions. As a workaround, ensure that the "USER $USERNAME" Dockerfile instruction is not used. Instead, set the container entrypoint to a value similar to ENTRYPOINT ["su", "-", "user"] to allow su to properly set up supplementary groups.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/containerd/containerdGo | < 1.5.18 | 1.5.18 |
github.com/containerd/containerdGo | >= 1.6.0, < 1.6.18 | 1.6.18 |
Affected products
1- Range: < 1.5.18
Patches
1133f6bb6cd82Merge pull request from GHSA-hmfx-3pcx-653p
5 files changed · +504 −79
integration/addition_gids_test.go+91 −41 modified@@ -20,6 +20,7 @@ package integration import ( + "fmt" "os" "path/filepath" "testing" @@ -31,49 +32,98 @@ import ( ) func TestAdditionalGids(t *testing.T) { - testPodLogDir, err := os.MkdirTemp("/tmp", "additional-gids") - require.NoError(t, err) - defer os.RemoveAll(testPodLogDir) + testImage := GetImage(BusyBox) + EnsureImageExists(t, testImage) + type testCase struct { + description string + opts []ContainerOpts + expected string + } - t.Log("Create a sandbox with log directory") - sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox", "additional-gids", - WithPodLogDirectory(testPodLogDir)) + testCases := []testCase{ + { + description: "Equivalent of `docker run` (no option)", + opts: nil, + expected: "groups=0(root),10(wheel)", + }, + { + description: "Equivalent of `docker run --group-add 1 --group-add 1234`", + opts: []ContainerOpts{WithSupplementalGroups([]int64{1 /*daemon*/, 1234 /*new group*/})}, + expected: "groups=0(root),1(daemon),10(wheel),1234", + }, + { + description: "Equivalent of `docker run --user 1234`", + opts: []ContainerOpts{WithRunAsUser(1234)}, + expected: "groups=0(root)", + }, + { + description: "Equivalent of `docker run --user 1234:1234`", + opts: []ContainerOpts{WithRunAsUser(1234), WithRunAsGroup(1234)}, + expected: "groups=1234", + }, + { + description: "Equivalent of `docker run --user 1234 --group-add 1234`", + opts: []ContainerOpts{WithRunAsUser(1234), WithSupplementalGroups([]int64{1234})}, + expected: "groups=0(root),1234", + }, + { + description: "Equivalent of `docker run --user daemon` (Supported by CRI, although unsupported by kube-apiserver)", + opts: []ContainerOpts{WithRunAsUsername("daemon")}, + expected: "groups=1(daemon)", + }, + { + description: "Equivalent of `docker run --user daemon --group-add 1234` (Supported by CRI, although unsupported by kube-apiserver)", + opts: []ContainerOpts{WithRunAsUsername("daemon"), WithSupplementalGroups([]int64{1234})}, + expected: "groups=1(daemon),1234", + }, + } - var ( - testImage = GetImage(BusyBox) - containerName = "test-container" - ) + for i, tc := range testCases { + i, tc := i, tc + tBasename := fmt.Sprintf("case-%d", i) + t.Run(tBasename, func(t *testing.T) { + t.Log(tc.description) + t.Logf("Expected=%q", tc.expected) - EnsureImageExists(t, testImage) + testPodLogDir := t.TempDir() + + t.Log("Create a sandbox with log directory") + sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox", tBasename, + WithPodLogDirectory(testPodLogDir)) + + t.Log("Create a container to print id") + containerName := tBasename + cnConfig := ContainerConfig( + containerName, + testImage, + append( + []ContainerOpts{ + WithCommand("id"), + WithLogPath(containerName), + }, tc.opts...)..., + ) + cn, err := runtimeService.CreateContainer(sb, cnConfig, sbConfig) + require.NoError(t, err) + + t.Log("Start the container") + require.NoError(t, runtimeService.StartContainer(cn)) + + t.Log("Wait for container to finish running") + require.NoError(t, Eventually(func() (bool, error) { + s, err := runtimeService.ContainerStatus(cn) + if err != nil { + return false, err + } + if s.GetState() == runtime.ContainerState_CONTAINER_EXITED { + return true, nil + } + return false, nil + }, time.Second, 30*time.Second)) - t.Log("Create a container to print id") - cnConfig := ContainerConfig( - containerName, - testImage, - WithCommand("id"), - WithLogPath(containerName), - WithSupplementalGroups([]int64{1 /*daemon*/, 1234 /*new group*/}), - ) - cn, err := runtimeService.CreateContainer(sb, cnConfig, sbConfig) - require.NoError(t, err) - - t.Log("Start the container") - require.NoError(t, runtimeService.StartContainer(cn)) - - t.Log("Wait for container to finish running") - require.NoError(t, Eventually(func() (bool, error) { - s, err := runtimeService.ContainerStatus(cn) - if err != nil { - return false, err - } - if s.GetState() == runtime.ContainerState_CONTAINER_EXITED { - return true, nil - } - return false, nil - }, time.Second, 30*time.Second)) - - t.Log("Search additional groups in container log") - content, err := os.ReadFile(filepath.Join(testPodLogDir, containerName)) - assert.NoError(t, err) - assert.Contains(t, string(content), "groups=1(daemon),10(wheel),1234") + t.Log("Search additional groups in container log") + content, err := os.ReadFile(filepath.Join(testPodLogDir, containerName)) + assert.NoError(t, err) + assert.Contains(t, string(content), tc.expected+"\n") + }) + } }
integration/main_test.go+39 −0 modified@@ -311,6 +311,45 @@ func WithLogPath(path string) ContainerOpts { } } +// WithRunAsUser sets the uid. +func WithRunAsUser(uid int64) ContainerOpts { + return func(c *runtime.ContainerConfig) { + if c.Linux == nil { + c.Linux = &runtime.LinuxContainerConfig{} + } + if c.Linux.SecurityContext == nil { + c.Linux.SecurityContext = &runtime.LinuxContainerSecurityContext{} + } + c.Linux.SecurityContext.RunAsUser = &runtime.Int64Value{Value: uid} + } +} + +// WithRunAsUsername sets the username. +func WithRunAsUsername(username string) ContainerOpts { + return func(c *runtime.ContainerConfig) { + if c.Linux == nil { + c.Linux = &runtime.LinuxContainerConfig{} + } + if c.Linux.SecurityContext == nil { + c.Linux.SecurityContext = &runtime.LinuxContainerSecurityContext{} + } + c.Linux.SecurityContext.RunAsUsername = username + } +} + +// WithRunAsGroup sets the gid. +func WithRunAsGroup(gid int64) ContainerOpts { + return func(c *runtime.ContainerConfig) { + if c.Linux == nil { + c.Linux = &runtime.LinuxContainerConfig{} + } + if c.Linux.SecurityContext == nil { + c.Linux.SecurityContext = &runtime.LinuxContainerSecurityContext{} + } + c.Linux.SecurityContext.RunAsGroup = &runtime.Int64Value{Value: gid} + } +} + // WithSupplementalGroups adds supplemental groups. func WithSupplementalGroups(gids []int64) ContainerOpts { //nolint:unused return func(c *runtime.ContainerConfig) {
oci/spec_opts.go+103 −37 modified@@ -113,6 +113,17 @@ func setCapabilities(s *Spec) { } } +// ensureAdditionalGids ensures that the primary GID is also included in the additional GID list. +func ensureAdditionalGids(s *Spec) { + setProcess(s) + for _, f := range s.Process.User.AdditionalGids { + if f == s.Process.User.GID { + return + } + } + s.Process.User.AdditionalGids = append([]uint32{s.Process.User.GID}, s.Process.User.AdditionalGids...) +} + // WithDefaultSpec returns a SpecOpts that will populate the spec with default // values. // @@ -522,7 +533,9 @@ func WithNamespacedCgroup() SpecOpts { // user, uid, user:group, uid:gid, uid:group, user:gid func WithUser(userstr string) SpecOpts { return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error { + defer ensureAdditionalGids(s) setProcess(s) + s.Process.User.AdditionalGids = nil // For LCOW it's a bit harder to confirm that the user actually exists on the host as a rootfs isn't // mounted on the host and shared into the guest, but rather the rootfs is constructed entirely in the @@ -615,7 +628,9 @@ func WithUser(userstr string) SpecOpts { // WithUIDGID allows the UID and GID for the Process to be set func WithUIDGID(uid, gid uint32) SpecOpts { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + defer ensureAdditionalGids(s) setProcess(s) + s.Process.User.AdditionalGids = nil s.Process.User.UID = uid s.Process.User.GID = gid return nil @@ -628,12 +643,11 @@ func WithUIDGID(uid, gid uint32) SpecOpts { // additionally sets the gid to 0, and does not return an error. func WithUserID(uid uint32) SpecOpts { return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { + defer ensureAdditionalGids(s) setProcess(s) - if c.Snapshotter == "" && c.SnapshotKey == "" { - if !isRootfsAbs(s.Root.Path) { - return errors.New("rootfs absolute path is required") - } - user, err := UserFromPath(s.Root.Path, func(u user.User) bool { + s.Process.User.AdditionalGids = nil + setUser := func(root string) error { + user, err := UserFromPath(root, func(u user.User) bool { return u.Uid == int(uid) }) if err != nil { @@ -645,7 +659,12 @@ func WithUserID(uid uint32) SpecOpts { } s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) return nil - + } + if c.Snapshotter == "" && c.SnapshotKey == "" { + if !isRootfsAbs(s.Root.Path) { + return errors.New("rootfs absolute path is required") + } + return setUser(s.Root.Path) } if c.Snapshotter == "" { return errors.New("no snapshotter set for container") @@ -660,20 +679,7 @@ func WithUserID(uid uint32) SpecOpts { } mounts = tryReadonlyMounts(mounts) - return mount.WithTempMount(ctx, mounts, func(root string) error { - user, err := UserFromPath(root, func(u user.User) bool { - return u.Uid == int(uid) - }) - if err != nil { - if os.IsNotExist(err) || err == ErrNoUsersFound { - s.Process.User.UID, s.Process.User.GID = uid, 0 - return nil - } - return err - } - s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) - return nil - }) + return mount.WithTempMount(ctx, mounts, setUser) } } @@ -685,13 +691,12 @@ func WithUserID(uid uint32) SpecOpts { // the container. func WithUsername(username string) SpecOpts { return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { + defer ensureAdditionalGids(s) setProcess(s) + s.Process.User.AdditionalGids = nil if s.Linux != nil { - if c.Snapshotter == "" && c.SnapshotKey == "" { - if !isRootfsAbs(s.Root.Path) { - return errors.New("rootfs absolute path is required") - } - user, err := UserFromPath(s.Root.Path, func(u user.User) bool { + setUser := func(root string) error { + user, err := UserFromPath(root, func(u user.User) bool { return u.Name == username }) if err != nil { @@ -700,6 +705,12 @@ func WithUsername(username string) SpecOpts { s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) return nil } + if c.Snapshotter == "" && c.SnapshotKey == "" { + if !isRootfsAbs(s.Root.Path) { + return errors.New("rootfs absolute path is required") + } + return setUser(s.Root.Path) + } if c.Snapshotter == "" { return errors.New("no snapshotter set for container") } @@ -713,16 +724,7 @@ func WithUsername(username string) SpecOpts { } mounts = tryReadonlyMounts(mounts) - return mount.WithTempMount(ctx, mounts, func(root string) error { - user, err := UserFromPath(root, func(u user.User) bool { - return u.Name == username - }) - if err != nil { - return err - } - s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) - return nil - }) + return mount.WithTempMount(ctx, mounts, setUser) } else if s.Windows != nil { s.Process.User.Username = username } else { @@ -733,7 +735,7 @@ func WithUsername(username string) SpecOpts { } // WithAdditionalGIDs sets the OCI spec's additionalGids array to any additional groups listed -// for a particular user in the /etc/groups file of the image's root filesystem +// for a particular user in the /etc/group file of the image's root filesystem // The passed in user can be either a uid or a username. func WithAdditionalGIDs(userstr string) SpecOpts { return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { @@ -742,7 +744,9 @@ func WithAdditionalGIDs(userstr string) SpecOpts { return nil } setProcess(s) + s.Process.User.AdditionalGids = nil setAdditionalGids := func(root string) error { + defer ensureAdditionalGids(s) var username string uid, err := strconv.Atoi(userstr) if err == nil { @@ -803,6 +807,68 @@ func WithAdditionalGIDs(userstr string) SpecOpts { } } +// WithAppendAdditionalGroups append additional groups within the container. +// The passed in groups can be either a gid or a groupname. +func WithAppendAdditionalGroups(groups ...string) SpecOpts { + return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { + // For LCOW or on Darwin additional GID's are not supported + if s.Windows != nil || runtime.GOOS == "darwin" { + return nil + } + setProcess(s) + setAdditionalGids := func(root string) error { + defer ensureAdditionalGids(s) + gpath, err := fs.RootPath(root, "/etc/group") + if err != nil { + return err + } + ugroups, err := user.ParseGroupFile(gpath) + if err != nil { + return err + } + groupMap := make(map[string]user.Group) + for _, group := range ugroups { + groupMap[group.Name] = group + } + var gids []uint32 + for _, group := range groups { + gid, err := strconv.ParseUint(group, 10, 32) + if err == nil { + gids = append(gids, uint32(gid)) + } else { + g, ok := groupMap[group] + if !ok { + return fmt.Errorf("unable to find group %s", group) + } + gids = append(gids, uint32(g.Gid)) + } + } + s.Process.User.AdditionalGids = append(s.Process.User.AdditionalGids, gids...) + return nil + } + if c.Snapshotter == "" && c.SnapshotKey == "" { + if !filepath.IsAbs(s.Root.Path) { + return errors.New("rootfs absolute path is required") + } + return setAdditionalGids(s.Root.Path) + } + if c.Snapshotter == "" { + return errors.New("no snapshotter set for container") + } + if c.SnapshotKey == "" { + return errors.New("rootfs snapshot not created for container") + } + snapshotter := client.SnapshotService(c.Snapshotter) + mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) + if err != nil { + return err + } + + mounts = tryReadonlyMounts(mounts) + return mount.WithTempMount(ctx, mounts, setAdditionalGids) + } +} + // WithCapabilities sets Linux capabilities on the process func WithCapabilities(caps []string) SpecOpts { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { @@ -907,7 +973,7 @@ func UserFromPath(root string, filter func(user.User) bool) (user.User, error) { // ErrNoGroupsFound can be returned from GIDFromPath var ErrNoGroupsFound = errors.New("no groups found") -// GIDFromPath inspects the GID using /etc/passwd in the specified rootfs. +// GIDFromPath inspects the GID using /etc/group in the specified rootfs. // filter can be nil. func GIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err error) { gpath, err := fs.RootPath(root, "/etc/group")
oci/spec_opts_linux_test.go+269 −0 modified@@ -18,15 +18,203 @@ package oci import ( "context" + "fmt" "os" "path/filepath" "testing" + "github.com/containerd/containerd/containers" "github.com/containerd/containerd/pkg/testutil" + "github.com/containerd/continuity/fs/fstest" specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/stretchr/testify/assert" "golang.org/x/sys/unix" ) +// nolint:gosec +func TestWithUserID(t *testing.T) { + t.Parallel() + + expectedPasswd := `root:x:0:0:root:/root:/bin/ash +guest:x:405:100:guest:/dev/null:/sbin/nologin +` + td := t.TempDir() + apply := fstest.Apply( + fstest.CreateDir("/etc", 0777), + fstest.CreateFile("/etc/passwd", []byte(expectedPasswd), 0777), + ) + if err := apply.Apply(td); err != nil { + t.Fatalf("failed to apply: %v", err) + } + c := containers.Container{ID: t.Name()} + testCases := []struct { + userID uint32 + expectedUID uint32 + expectedGID uint32 + }{ + { + userID: 0, + expectedUID: 0, + expectedGID: 0, + }, + { + userID: 405, + expectedUID: 405, + expectedGID: 100, + }, + { + userID: 1000, + expectedUID: 1000, + expectedGID: 0, + }, + } + for _, testCase := range testCases { + testCase := testCase + t.Run(fmt.Sprintf("user %d", testCase.userID), func(t *testing.T) { + t.Parallel() + s := Spec{ + Version: specs.Version, + Root: &specs.Root{ + Path: td, + }, + Linux: &specs.Linux{}, + } + err := WithUserID(testCase.userID)(context.Background(), nil, &c, &s) + assert.NoError(t, err) + assert.Equal(t, testCase.expectedUID, s.Process.User.UID) + assert.Equal(t, testCase.expectedGID, s.Process.User.GID) + }) + } +} + +// nolint:gosec +func TestWithUsername(t *testing.T) { + t.Parallel() + + expectedPasswd := `root:x:0:0:root:/root:/bin/ash +guest:x:405:100:guest:/dev/null:/sbin/nologin +` + td := t.TempDir() + apply := fstest.Apply( + fstest.CreateDir("/etc", 0777), + fstest.CreateFile("/etc/passwd", []byte(expectedPasswd), 0777), + ) + if err := apply.Apply(td); err != nil { + t.Fatalf("failed to apply: %v", err) + } + c := containers.Container{ID: t.Name()} + testCases := []struct { + user string + expectedUID uint32 + expectedGID uint32 + err string + }{ + { + user: "root", + expectedUID: 0, + expectedGID: 0, + }, + { + user: "guest", + expectedUID: 405, + expectedGID: 100, + }, + { + user: "1000", + err: "no users found", + }, + { + user: "unknown", + err: "no users found", + }, + } + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.user, func(t *testing.T) { + t.Parallel() + s := Spec{ + Version: specs.Version, + Root: &specs.Root{ + Path: td, + }, + Linux: &specs.Linux{}, + } + err := WithUsername(testCase.user)(context.Background(), nil, &c, &s) + if err != nil { + assert.EqualError(t, err, testCase.err) + } + assert.Equal(t, testCase.expectedUID, s.Process.User.UID) + assert.Equal(t, testCase.expectedGID, s.Process.User.GID) + }) + } + +} + +// nolint:gosec +func TestWithAdditionalGIDs(t *testing.T) { + t.Parallel() + expectedPasswd := `root:x:0:0:root:/root:/bin/ash +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +` + expectedGroup := `root:x:0:root +bin:x:1:root,bin,daemon +daemon:x:2:root,bin,daemon +sys:x:3:root,bin,adm +` + td := t.TempDir() + apply := fstest.Apply( + fstest.CreateDir("/etc", 0777), + fstest.CreateFile("/etc/passwd", []byte(expectedPasswd), 0777), + fstest.CreateFile("/etc/group", []byte(expectedGroup), 0777), + ) + if err := apply.Apply(td); err != nil { + t.Fatalf("failed to apply: %v", err) + } + c := containers.Container{ID: t.Name()} + + testCases := []struct { + user string + expected []uint32 + }{ + { + user: "root", + expected: []uint32{0, 1, 2, 3}, + }, + { + user: "1000", + expected: []uint32{0}, + }, + { + user: "bin", + expected: []uint32{0, 2, 3}, + }, + { + user: "bin:root", + expected: []uint32{0}, + }, + { + user: "daemon", + expected: []uint32{0, 1}, + }, + } + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.user, func(t *testing.T) { + t.Parallel() + s := Spec{ + Version: specs.Version, + Root: &specs.Root{ + Path: td, + }, + } + err := WithAdditionalGIDs(testCase.user)(context.Background(), nil, &c, &s) + assert.NoError(t, err) + assert.Equal(t, testCase.expected, s.Process.User.AdditionalGids) + }) + } +} + func TestAddCaps(t *testing.T) { t.Parallel() @@ -247,3 +435,84 @@ func TestGetDevices(t *testing.T) { }) }) } + +func TestWithAppendAdditionalGroups(t *testing.T) { + t.Parallel() + expectedContent := `root:x:0:root +bin:x:1:root,bin,daemon +daemon:x:2:root,bin,daemon +` + td := t.TempDir() + apply := fstest.Apply( + fstest.CreateDir("/etc", 0777), + fstest.CreateFile("/etc/group", []byte(expectedContent), 0777), + ) + if err := apply.Apply(td); err != nil { + t.Fatalf("failed to apply: %v", err) + } + c := containers.Container{ID: t.Name()} + + testCases := []struct { + name string + additionalGIDs []uint32 + groups []string + expected []uint32 + err string + }{ + { + name: "no additional gids", + groups: []string{}, + expected: []uint32{0}, + }, + { + name: "no additional gids, append root gid", + groups: []string{"root"}, + expected: []uint32{0}, + }, + { + name: "no additional gids, append bin and daemon gids", + groups: []string{"bin", "daemon"}, + expected: []uint32{0, 1, 2}, + }, + { + name: "has root additional gids, append bin and daemon gids", + additionalGIDs: []uint32{0}, + groups: []string{"bin", "daemon"}, + expected: []uint32{0, 1, 2}, + }, + { + name: "append group id", + groups: []string{"999"}, + expected: []uint32{0, 999}, + }, + { + name: "unknown group", + groups: []string{"unknown"}, + err: "unable to find group unknown", + expected: []uint32{0}, + }, + } + + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + s := Spec{ + Version: specs.Version, + Root: &specs.Root{ + Path: td, + }, + Process: &specs.Process{ + User: specs.User{ + AdditionalGids: testCase.additionalGIDs, + }, + }, + } + err := WithAppendAdditionalGroups(testCase.groups...)(context.Background(), nil, &c, &s) + if err != nil { + assert.EqualError(t, err, testCase.err) + } + assert.Equal(t, testCase.expected, s.Process.User.AdditionalGids) + }) + } +}
pkg/cri/server/container_create_linux.go+2 −1 modified@@ -348,7 +348,8 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon // Because it is still useful to get additional gids for uid 0. userstr = strconv.FormatInt(securityContext.GetRunAsUser().GetValue(), 10) } - specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr)) + specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr), + customopts.WithSupplementalGroups(securityContext.GetSupplementalGroups())) asp := securityContext.GetApparmor() if asp == nil {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
19- github.com/advisories/GHSA-4wjj-jwc9-2x96ghsax_refsource_MISCADVISORY
- github.com/advisories/GHSA-fjm8-m7m6-2fjpghsax_refsource_MISCADVISORY
- github.com/advisories/GHSA-hmfx-3pcx-653pghsaADVISORY
- github.com/advisories/GHSA-phjr-8j92-w5v7ghsax_refsource_MISCADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-25173ghsaADVISORY
- github.com/containerd/containerd/commit/133f6bb6cd827ce35a5fb279c1ead12b9d21460aghsax_refsource_MISCWEB
- github.com/containerd/containerd/releases/tag/v1.5.18ghsax_refsource_MISCWEB
- github.com/containerd/containerd/releases/tag/v1.6.18ghsax_refsource_MISCWEB
- github.com/containerd/containerd/security/advisories/GHSA-hmfx-3pcx-653pghsax_refsource_CONFIRMWEB
- github.com/moby/moby/security/advisories/GHSA-rc4r-wh2q-q6c4ghsax_refsource_MISCWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/LYZOKMMVX4SIEHPJW3SJUQGMO5YZCPHCghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XNF4OLYZRQE75EB5TW5N42FSXHBXGWFEghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ZTE4ITXXPIWZEQ4HYQCB6N6GZIMWXDAIghsaWEB
- pkg.go.dev/vuln/GO-2023-1574ghsaWEB
- www.benthamsgaze.org/2022/08/22/vulnerability-in-linux-containers-investigation-and-mitigationghsaWEB
- www.benthamsgaze.org/2022/08/22/vulnerability-in-linux-containers-investigation-and-mitigation/mitrex_refsource_MISC
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/LYZOKMMVX4SIEHPJW3SJUQGMO5YZCPHC/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XNF4OLYZRQE75EB5TW5N42FSXHBXGWFE/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ZTE4ITXXPIWZEQ4HYQCB6N6GZIMWXDAI/mitre
News mentions
0No linked articles in our index yet.