From fd80f8d96f44da28704e39652e1d02a013ff5e08 Mon Sep 17 00:00:00 2001 From: Aman Gautam Date: Thu, 16 Jul 2026 15:11:29 +0530 Subject: [PATCH] Fix host UID/GID leakage in copyFileToContainer TAR entries --- .../testcontainers/utility/MountableFile.java | 4 ++++ .../utility/MountableFileTest.java | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/core/src/main/java/org/testcontainers/utility/MountableFile.java b/core/src/main/java/org/testcontainers/utility/MountableFile.java index a8a9f465a19..d51aea069fa 100644 --- a/core/src/main/java/org/testcontainers/utility/MountableFile.java +++ b/core/src/main/java/org/testcontainers/utility/MountableFile.java @@ -353,6 +353,10 @@ private void recursiveTar( } final TarArchiveEntry tarEntry = new TarArchiveEntry(sourceFile, tarEntryFilename.replaceAll("^/", "")); + tarEntry.setUserId(0); + tarEntry.setGroupId(0); + tarEntry.setUserName("root"); + tarEntry.setGroupName("root"); // TarArchiveEntry automatically sets the mode for file/directory, but we can update to ensure that the mode is set exactly (inc executable bits) tarEntry.setMode(getUnixFileMode(itemPath)); diff --git a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java index 72db429c263..1f33ea751dc 100644 --- a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java +++ b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java @@ -2,6 +2,7 @@ import lombok.Cleanup; import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.jetbrains.annotations.NotNull; @@ -32,6 +33,27 @@ void forClasspathResource() throws Exception { performChecks(mountableFile); } + @Test + void tarEntriesShouldUseRootOwnership() throws Exception { + final Path file = createTempFile("ownership-test.txt"); + final MountableFile mountableFile = MountableFile.forHostPath(file); + + @Cleanup + final TarArchiveInputStream tais = intoTarArchive(taos -> { + mountableFile.transferTo(taos, "/ownership-test.txt"); + }); + + final TarArchiveEntry tarEntry = tais.getNextEntry(); + + assertThat(tarEntry).isNotNull(); + + System.out.println("UID = " + tarEntry.getLongUserId()); + System.out.println("GID = " + tarEntry.getLongGroupId()); + + assertThat(tarEntry.getLongUserId()).isZero(); + assertThat(tarEntry.getLongGroupId()).isZero(); + } + @Test void forClasspathResourceWithAbsolutePath() throws Exception { final MountableFile mountableFile = MountableFile.forClasspathResource("/mappable-resource/test-resource.txt");