Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package plexus-utils for openSUSE:Factory checked in at 2026-03-26 21:08:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/plexus-utils (Old) and /work/SRC/openSUSE:Factory/.plexus-utils.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "plexus-utils" Thu Mar 26 21:08:33 2026 rev:12 rq:1342703 version:4.0.2 Changes: -------- --- /work/SRC/openSUSE:Factory/plexus-utils/plexus-utils.changes 2024-10-08 17:25:35.695998965 +0200 +++ /work/SRC/openSUSE:Factory/.plexus-utils.new.8177/plexus-utils.changes 2026-03-27 06:46:50.011357305 +0100 @@ -1,0 +2,8 @@ +Thu Mar 26 05:20:57 UTC 2026 - Fridrich Strba <[email protected]> + +- Added patch: + * plexus-utils-CVE-2025-67030.patch + + fixing bsc#1260588, CVE-2025-67030: directory traversal via + the 'extractFile' method of 'org.codehaus.plexus.util.Expand' + +------------------------------------------------------------------- New: ---- _scmsync.obsinfo build.specials.obscpio plexus-utils-CVE-2025-67030.patch ----------(New B)---------- New:- Added patch: * plexus-utils-CVE-2025-67030.patch + fixing bsc#1260588, CVE-2025-67030: directory traversal via ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ plexus-utils.spec ++++++ --- /var/tmp/diff_new_pack.BEWK69/_old 2026-03-27 06:46:50.611382073 +0100 +++ /var/tmp/diff_new_pack.BEWK69/_new 2026-03-27 06:46:50.615382238 +0100 @@ -25,6 +25,7 @@ URL: https://codehaus-plexus.github.io/plexus-utils/ Source0: https://github.com/codehaus-plexus/%{name}/archive/%{name}-%{version}.tar.gz Source1: %{name}-build.xml +Patch0: plexus-utils-CVE-2025-67030.patch BuildRequires: ant BuildRequires: fdupes BuildRequires: javapackages-local >= 6 @@ -47,6 +48,7 @@ %prep %setup -q -n %{name}-%{name}-%{version} +%patch -P 0 -p1 cp %{SOURCE1} build.xml mkdir -p lib ++++++ _scmsync.obsinfo ++++++ mtime: 1774502605 commit: 9893d2b935968f426feee3dc51e6b5a697d2bd75acfd72db2164ccb2f7bfc108 url: https://src.opensuse.org/java-packages/plexus-utils.git revision: 9893d2b935968f426feee3dc51e6b5a697d2bd75acfd72db2164ccb2f7bfc108 projectscmsync: https://src.opensuse.org/java-packages/_ObsPrj ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-03-26 06:24:07.000000000 +0100 @@ -0,0 +1 @@ +.osc ++++++ plexus-utils-CVE-2025-67030.patch ++++++ >From 6d780b3378829318ba5c2d29547e0012d5b29642 Mon Sep 17 00:00:00 2001 From: Copilot <[email protected]> Date: Sun, 9 Nov 2025 12:32:38 +0100 Subject: [PATCH] Fix Zip Slip vulnerability in archive extraction (#296) --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: slachiewicz <[email protected]> --- .../java/org/codehaus/plexus/util/Expand.java | 15 +- .../org/codehaus/plexus/util/ExpandTest.java | 148 ++++++++++++++++++ 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 src/test/java/org/codehaus/plexus/util/ExpandTest.java diff --git a/src/main/java/org/codehaus/plexus/util/Expand.java b/src/main/java/org/codehaus/plexus/util/Expand.java index 8abcdd95..6ac71dc1 100644 --- a/src/main/java/org/codehaus/plexus/util/Expand.java +++ b/src/main/java/org/codehaus/plexus/util/Expand.java @@ -111,8 +111,19 @@ protected void extractFile( throws Exception { File f = FileUtils.resolveFile(dir, entryName); - if (!f.getAbsolutePath().startsWith(dir.getAbsolutePath())) { - throw new IOException("Entry '" + entryName + "' outside the target directory."); + try { + String canonicalDirPath = dir.getCanonicalPath(); + String canonicalFilePath = f.getCanonicalPath(); + + // Ensure the file is within the target directory + // We need to check that the canonical file path starts with the canonical directory path + // followed by a file separator to prevent path traversal attacks + if (!canonicalFilePath.startsWith(canonicalDirPath + File.separator) + && !canonicalFilePath.equals(canonicalDirPath)) { + throw new IOException("Entry '" + entryName + "' outside the target directory."); + } + } catch (IOException e) { + throw new IOException("Failed to verify entry path for '" + entryName + "'", e); } try { diff --git a/src/test/java/org/codehaus/plexus/util/ExpandTest.java b/src/test/java/org/codehaus/plexus/util/ExpandTest.java new file mode 100644 index 00000000..46e3d0e3 --- /dev/null +++ b/src/test/java/org/codehaus/plexus/util/ExpandTest.java @@ -0,0 +1,148 @@ +package org.codehaus.plexus.util; + +/* + * Copyright The Codehaus Foundation. + * + * 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. + */ + +import java.io.File; +import java.nio.file.Files; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Test for {@link Expand}. + */ +class ExpandTest extends FileBasedTestCase { + + @Test + void testZipSlipVulnerabilityWithParentDirectory() throws Exception { + File tempDir = getTestDirectory(); + File zipFile = new File(tempDir, "malicious.zip"); + File targetDir = new File(tempDir, "extract"); + targetDir.mkdirs(); + + // Create a malicious zip with path traversal + try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zipFile.toPath()))) { + ZipEntry entry = new ZipEntry("../../evil.txt"); + zos.putNextEntry(entry); + zos.write("malicious content".getBytes()); + zos.closeEntry(); + } + + Expand expand = new Expand(); + expand.setSrc(zipFile); + expand.setDest(targetDir); + + // This should throw an exception, not extract the file + assertThrows(Exception.class, () -> expand.execute()); + + // Verify the file was not created outside the target directory + File evilFile = new File(tempDir, "evil.txt"); + assertFalse(evilFile.exists(), "File should not be extracted outside target directory"); + } + + @Test + void testZipSlipVulnerabilityWithAbsolutePath() throws Exception { + File tempDir = getTestDirectory(); + File zipFile = new File(tempDir, "malicious-absolute.zip"); + File targetDir = new File(tempDir, "extract-abs"); + targetDir.mkdirs(); + + // Create a malicious zip with absolute path + File evilTarget = new File("/tmp/evil-absolute.txt"); + try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zipFile.toPath()))) { + ZipEntry entry = new ZipEntry(evilTarget.getAbsolutePath()); + zos.putNextEntry(entry); + zos.write("malicious content".getBytes()); + zos.closeEntry(); + } + + Expand expand = new Expand(); + expand.setSrc(zipFile); + expand.setDest(targetDir); + + // This should throw an exception, not extract the file + assertThrows(Exception.class, () -> expand.execute()); + + // Verify the file was not created at the absolute path + assertFalse(evilTarget.exists(), "File should not be extracted to absolute path"); + } + + @Test + void testZipSlipVulnerabilityWithSimilarDirectoryName() throws Exception { + File tempDir = getTestDirectory(); + File zipFile = new File(tempDir, "malicious-similar.zip"); + File targetDir = new File(tempDir, "extract"); + targetDir.mkdirs(); + + // Create a directory with a similar name to test prefix matching vulnerability + File similarDir = new File(tempDir, "extract-evil"); + similarDir.mkdirs(); + + // Create a malicious zip that tries to exploit prefix matching + // If targetDir is /tmp/extract, this tries to write to /tmp/extract-evil/file.txt + String maliciousPath = "../extract-evil/evil.txt"; + try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zipFile.toPath()))) { + ZipEntry entry = new ZipEntry(maliciousPath); + zos.putNextEntry(entry); + zos.write("malicious content".getBytes()); + zos.closeEntry(); + } + + Expand expand = new Expand(); + expand.setSrc(zipFile); + expand.setDest(targetDir); + + // This should throw an exception, not extract the file + assertThrows(Exception.class, () -> expand.execute()); + + // Verify the file was not created in the similar directory + File evilFile = new File(similarDir, "evil.txt"); + assertFalse(evilFile.exists(), "File should not be extracted to directory with similar name"); + } + + @Test + void testNormalZipExtraction() throws Exception { + File tempDir = getTestDirectory(); + File zipFile = new File(tempDir, "normal.zip"); + File targetDir = new File(tempDir, "extract-normal"); + targetDir.mkdirs(); + + // Create a normal zip + try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zipFile.toPath()))) { + ZipEntry entry = new ZipEntry("subdir/normal.txt"); + zos.putNextEntry(entry); + zos.write("normal content".getBytes()); + zos.closeEntry(); + } + + Expand expand = new Expand(); + expand.setSrc(zipFile); + expand.setDest(targetDir); + + // This should succeed + expand.execute(); + + // Verify the file was created in the correct location + File normalFile = new File(targetDir, "subdir/normal.txt"); + assertTrue(normalFile.exists(), "File should be extracted to correct location"); + } +}
