diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index bd462d93b..96758801f 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -308,6 +308,15 @@ protected void extractFile( final File srcF, final File dir, final InputStream c // Hmm. Symlinks re-evaluate back to the original file here. Unsure if this is a good thing... final File f = FileUtils.resolveFile( dir, entryName ); + // Make sure that the resolved path of the extracted file doesn't escape the destination directory + String canonicalDirPath = dir.getCanonicalPath(); + String canonicalDestPath = f.getCanonicalPath(); + + if ( !canonicalDestPath.startsWith( canonicalDirPath ) ) + { + throw new ArchiverException( "Entry is outside of the target directory (" + entryName + ")" ); + } + try { if ( !isOverwrite() && f.exists() && ( f.lastModified() >= entryDate.getTime() ) ) diff --git a/src/test/java/org/codehaus/plexus/archiver/zip/ZipUnArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/zip/ZipUnArchiverTest.java index 1f72a6156..ea46a5aae 100644 --- a/src/test/java/org/codehaus/plexus/archiver/zip/ZipUnArchiverTest.java +++ b/src/test/java/org/codehaus/plexus/archiver/zip/ZipUnArchiverTest.java @@ -190,6 +190,30 @@ public void testSelectors() } ); } + public void testExtractingZipWithEntryOutsideDestDirThrowsException() + throws Exception + { + Exception ex = null; + String s = "target/zip-unarchiver-slip-tests"; + File testZip = new File( getBasedir(), "src/test/zips/zip-slip.zip" ); + File outputDirectory = new File( getBasedir(), s ); + + FileUtils.deleteDirectory( outputDirectory ); + + try + { + ZipUnArchiver zu = getZipUnArchiver( testZip ); + zu.extract( "", outputDirectory ); + } + catch ( Exception e ) + { + ex = e; + } + + assertNotNull( ex ); + assertTrue( ex.getMessage().startsWith( "Entry is outside of the target directory" ) ); + } + private ZipArchiver getZipArchiver() { try diff --git a/src/test/zips/zip-slip.zip b/src/test/zips/zip-slip.zip new file mode 100644 index 000000000..38b3f499d Binary files /dev/null and b/src/test/zips/zip-slip.zip differ