diff --git a/spring-boot-project/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/ProjectGenerator.java b/spring-boot-project/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/ProjectGenerator.java index bb95b8632a7..14a87b74933 100644 --- a/spring-boot-project/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/ProjectGenerator.java +++ b/spring-boot-project/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/ProjectGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -117,8 +117,17 @@ class ProjectGenerator { private void extractFromStream(ZipInputStream zipStream, boolean overwrite, File outputFolder) throws IOException { ZipEntry entry = zipStream.getNextEntry(); + String canonicalOutputPath = outputFolder.getCanonicalPath() + File.separator; while (entry != null) { File file = new File(outputFolder, entry.getName()); + String canonicalEntryPath = file.getCanonicalPath(); + if (!canonicalEntryPath.startsWith(canonicalOutputPath)) { + throw new ReportableException("Entry '" + entry.getName() + + "' would be written to '" + canonicalEntryPath + + "'. This is outside the output location of '" + + canonicalOutputPath + + "'. Verify your target server configuration."); + } if (file.exists() && !overwrite) { throw new ReportableException((file.isDirectory() ? "Directory" : "File") + " '" + file.getName() diff --git a/spring-boot-project/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java b/spring-boot-project/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java index 360d7b0d357..ea3b463c8ee 100644 --- a/spring-boot-project/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java +++ b/spring-boot-project/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -125,6 +125,20 @@ public class InitCommandTests extends AbstractHttpClientMockTests { assertThat(archiveFile).exists(); } + @Test + public void generateProjectAndExtractWillNotWriteEntriesOutsideOutputLocation() + throws Exception { + File folder = this.temporaryFolder.newFolder(); + byte[] archive = createFakeZipArchive("../outside.txt", "Fake content"); + MockHttpProjectGenerationRequest request = new MockHttpProjectGenerationRequest( + "application/zip", "demo.zip", archive); + mockSuccessfulProjectGeneration(request); + assertThat(this.command.run("--extract", folder.getAbsolutePath())) + .isEqualTo(ExitStatus.ERROR); + File archiveFile = new File(folder.getParentFile(), "outside.txt"); + assertThat(archiveFile).doesNotExist(); + } + @Test public void generateProjectAndExtractWithConvention() throws Exception { File folder = this.temporaryFolder.newFolder();