From 9e040ee8dd6025558ea60ac9db60c41bfeddf221 Mon Sep 17 00:00:00 2001 From: Praveen Kumar Date: Mon, 14 Apr 2025 13:29:56 +0000 Subject: [PATCH] buildah: Fix CVE-2024-9675 A vulnerability was found in Buildah. Cache mounts do not properly validate that user-specified paths for the cache are within our cache directory, allowing a `RUN` instruction in a Container file to mount an arbitrary directory from the host (read/write) into the container as long as those files can be accessed by the user running Buildah. References: https://nvd.nist.gov/vuln/detail/CVE-2024-9675 https://security-tracker.debian.org/tracker/CVE-2024-9675 Upstream-patch: https://github.com/containers/buildah/commit/cffa820dc8be07efdb7fc4e8e8b9ff44c70aaf93 Signed-off-by: Praveen Kumar Signed-off-by: Bruce Ashfield --- .../buildah/buildah/CVE-2024-9675.patch | 113 ++++++++++++++++++ recipes-containers/buildah/buildah_git.bb | 1 + 2 files changed, 114 insertions(+) create mode 100644 recipes-containers/buildah/buildah/CVE-2024-9675.patch diff --git a/recipes-containers/buildah/buildah/CVE-2024-9675.patch b/recipes-containers/buildah/buildah/CVE-2024-9675.patch new file mode 100644 index 00000000..6a655366 --- /dev/null +++ b/recipes-containers/buildah/buildah/CVE-2024-9675.patch @@ -0,0 +1,113 @@ +From cffa820dc8be07efdb7fc4e8e8b9ff44c70aaf93 Mon Sep 17 00:00:00 2001 +From: Matt Heon +Date: Wed, 9 Oct 2024 15:23:03 -0400 +Subject: [PATCH] Properly validate cache IDs and sources + +The `--mount type=cache` argument to the `RUN` instruction in +Dockerfiles was using `filepath.Join` on user input, allowing +crafted paths to be used to gain access to paths on the host, +when the command should normally be limited only to Buildah;s own +cache and context directories. Switch to `filepath.SecureJoin` to +resolve the issue. + +Fixes CVE-2024-9675 + +CVE: CVE-2024-9675 + +Upstream-Status: Backport [https://github.com/containers/buildah/commit/cffa820dc8be07efdb7fc4e8e8b9ff44c70aaf93] + +Signed-off-by: Praveen Kumar +--- + internal/volumes/volumes.go | 19 ++++++++++++++----- + tests/bud.bats | 34 ++++++++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+), 5 deletions(-) + +diff --git a/internal/volumes/volumes.go b/internal/volumes/volumes.go +index c07c67ebe..c6d6e3545 100644 +--- a/internal/volumes/volumes.go ++++ b/internal/volumes/volumes.go +@@ -23,6 +23,7 @@ import ( + "github.com/containers/storage/pkg/idtools" + "github.com/containers/storage/pkg/lockfile" + "github.com/containers/storage/pkg/unshare" ++ digest "github.com/opencontainers/go-digest" + specs "github.com/opencontainers/runtime-spec/specs-go" + selinux "github.com/opencontainers/selinux/go-selinux" + ) +@@ -362,7 +363,11 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a + return newMount, nil, fmt.Errorf("no stage found with name %s", fromStage) + } + // path should be /contextDir/specified path +- newMount.Source = filepath.Join(mountPoint, filepath.Clean(string(filepath.Separator)+newMount.Source)) ++ evaluated, err := copier.Eval(mountPoint, string(filepath.Separator)+newMount.Source, copier.EvalOptions{}) ++ if err != nil { ++ return newMount, nil, err ++ } ++ newMount.Source = evaluated + } else { + // we need to create cache on host if no image is being used + +@@ -379,11 +384,15 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a + } + + if id != "" { +- newMount.Source = filepath.Join(cacheParent, filepath.Clean(id)) +- buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, filepath.Clean(id)) ++ // Don't let the user control where we place the directory. ++ dirID := digest.FromString(id).Encoded()[:16] ++ newMount.Source = filepath.Join(cacheParent, dirID) ++ buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, dirID) + } else { +- newMount.Source = filepath.Join(cacheParent, filepath.Clean(newMount.Destination)) +- buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, filepath.Clean(newMount.Destination)) ++ // Don't let the user control where we place the directory. ++ dirID := digest.FromString(newMount.Destination).Encoded()[:16] ++ newMount.Source = filepath.Join(cacheParent, dirID) ++ buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, dirID) + } + idPair := idtools.IDPair{ + UID: uid, +diff --git a/tests/bud.bats b/tests/bud.bats +index 3a1dbd63a..9e3930f52 100644 +--- a/tests/bud.bats ++++ b/tests/bud.bats +@@ -6648,3 +6648,37 @@ _EOF + assert "$status" -eq 2 "exit code from ls" + expect_output --substring "No such file or directory" + } ++ ++@test "build-check-cve-2024-9675" { ++ _prefetch alpine ++ ++ touch ${TEST_SCRATCH_DIR}/file.txt ++ ++ cat > ${TEST_SCRATCH_DIR}/Containerfile < ${TEST_SCRATCH_DIR}/Containerfile < ${TEST_SCRATCH_DIR}/cve20249675/Containerfile <