VYPR
High severity8.8NVD Advisory· Published Mar 25, 2026· Updated May 1, 2026

CVE-2025-67030

CVE-2025-67030

Description

Directory Traversal vulnerability in the extractFile method of org.codehaus.plexus.util.Expand in plexus-utils before 6d780b3378829318ba5c2d29547e0012d5b29642. This allows an attacker to execute arbitrary code

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.codehaus.plexus:plexus-utilsMaven
>= 4.0.0, < 4.0.34.0.3
org.codehaus.plexus:plexus-utilsMaven
< 3.6.13.6.1

Affected products

1

Patches

1
6d780b337882

Fix Zip Slip vulnerability in archive extraction (#296)

2 files changed · +161 2
  • src/main/java/org/codehaus/plexus/util/Expand.java+13 2 modified
    @@ -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 {
    
  • src/test/java/org/codehaus/plexus/util/ExpandTest.java+148 0 added
    @@ -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");
    +    }
    +}
    

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

8

News mentions

0

No linked articles in our index yet.