Skip to content

Commit 0f27b1a

Browse files
committed
Verify entry output location when extracting zip
Closes gh-16028
1 parent 30bba53 commit 0f27b1a

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/ProjectGenerator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2018 the original author or authors.
2+
* Copyright 2012-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -122,8 +122,17 @@ private void extractProject(ProjectGenerationResponse entity, String output,
122122
private void extractFromStream(ZipInputStream zipStream, boolean overwrite,
123123
File outputFolder) throws IOException {
124124
ZipEntry entry = zipStream.getNextEntry();
125+
String canonicalOutputPath = outputFolder.getCanonicalPath() + File.separator;
125126
while (entry != null) {
126127
File file = new File(outputFolder, entry.getName());
128+
String canonicalEntryPath = file.getCanonicalPath();
129+
if (!canonicalEntryPath.startsWith(canonicalOutputPath)) {
130+
throw new ReportableException("Entry '" + entry.getName()
131+
+ "' would be written to '" + canonicalEntryPath
132+
+ "'. This is outside the output location of '"
133+
+ canonicalOutputPath
134+
+ "'. Verify your target server configuration.");
135+
}
127136
if (file.exists() && !overwrite) {
128137
throw new ReportableException((file.isDirectory() ? "Directory" : "File")
129138
+ " '" + file.getName()

spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -125,6 +125,20 @@ public void generateProjectAndExtract() throws Exception {
125125
assertThat(archiveFile).exists();
126126
}
127127

128+
@Test
129+
public void generateProjectAndExtractWillNotWriteEntriesOutsideOutputLocation()
130+
throws Exception {
131+
File folder = this.temporaryFolder.newFolder();
132+
byte[] archive = createFakeZipArchive("../outside.txt", "Fake content");
133+
MockHttpProjectGenerationRequest request = new MockHttpProjectGenerationRequest(
134+
"application/zip", "demo.zip", archive);
135+
mockSuccessfulProjectGeneration(request);
136+
assertThat(this.command.run("--extract", folder.getAbsolutePath()))
137+
.isEqualTo(ExitStatus.ERROR);
138+
File archiveFile = new File(folder.getParentFile(), "outside.txt");
139+
assertThat(archiveFile).doesNotExist();
140+
}
141+
128142
@Test
129143
public void generateProjectAndExtractWithConvention() throws Exception {
130144
File folder = this.temporaryFolder.newFolder();

0 commit comments

Comments
 (0)