Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,10 @@ private void recursiveTar(

// 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));
// Avoid propagating host UID/GID into containers. This is important for rootless Docker setups
// where host IDs may be unmapped and cause permission issues after copyArchiveToContainer.
tarEntry.setUserId(0);
tarEntry.setGroupId(0);
tarArchive.putArchiveEntry(tarEntry);

if (sourceFile.isFile()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -131,6 +132,20 @@ void noTrailingSlashesInTarEntryNames() throws Exception {
}
}

@Test
void tarEntriesShouldUseRootOwnership() throws Exception {
final Path file = createTempFile("owner-check.txt");
final MountableFile mountableFile = MountableFile.forHostPath(file.toString());

@Cleanup
final TarArchiveInputStream tais = intoTarArchive(taos -> mountableFile.transferTo(taos, "/owner-check.txt"));

final TarArchiveEntry entry = tais.getNextTarEntry();
assertThat(entry).isNotNull();
assertThat(entry.getLongUserId()).as("tar user id should not leak host uid").isZero();
assertThat(entry.getLongGroupId()).as("tar group id should not leak host gid").isZero();
}

private TarArchiveInputStream intoTarArchive(Consumer<TarArchiveOutputStream> consumer) throws IOException {
@Cleanup
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
Expand Down