Skip to content

Commit b885b03

Browse files
authored
Merge pull request from GHSA-qh4g-4m4w-jgv2
Fix partial path traversal in zip file overwite protection
2 parents 7c8e93e + 98bb779 commit b885b03

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,22 @@ In Maven:
3535
<dependency>
3636
<groupId>io.github.pixee</groupId>
3737
<artifactId>java-security-toolkit</artifactId>
38-
<version>1.1.1</version>
38+
<version>1.1.2</version>
3939
</dependency>
4040
```
4141
In Gradle:
4242
```kotlin
43-
implementation("io.github.pixee:java-security-toolkit:1.1.1")
43+
implementation("io.github.pixee:java-security-toolkit:1.1.2")
4444
```
4545

4646
## Contributing
4747
We'd love to get contributions! See [CONTRIBUTING.md](CONTRIBUTING.md).
4848

4949
### Building
50-
Building is meant for Java 11 and Maven 3:
50+
Building is meant for Java 11:
5151

5252
```
53-
mvn clean package
53+
./gradlew check
5454
```
5555

5656
## FAQ

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ tasks.named(java11SourceSet.jarTaskName) {
9191
}
9292

9393
group = "io.github.pixee"
94-
version = "1.1.1"
94+
version = "1.1.2"
9595
description = "java-security-toolkit"
9696

9797

src/main/java/io/github/pixee/security/ZipSecurity.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.io.IOException;
55
import java.io.InputStream;
66
import java.nio.charset.Charset;
7+
import java.nio.file.Path;
78
import java.util.zip.ZipEntry;
89
import java.util.zip.ZipInputStream;
910

@@ -67,9 +68,8 @@ public ZipEntry getNextEntry() throws IOException {
6768

6869
private boolean containsEscapesAndTargetsBelowRoot(final String name) {
6970
if (name.contains("../") || name.contains("..\\")) {
70-
final File fileWithEscapes = new File(name);
7171
try {
72-
if (isBelowCurrentDirectory(fileWithEscapes)) {
72+
if (isBelowOrSisterToCurrentDirectory(name)) {
7373
return true;
7474
}
7575
} catch (IOException e) {
@@ -79,11 +79,14 @@ private boolean containsEscapesAndTargetsBelowRoot(final String name) {
7979
return false;
8080
}
8181

82-
boolean isBelowCurrentDirectory(final File fileWithEscapes) throws IOException {
83-
final File currentDirectory = new File("");
84-
String canonicalizedTargetPath = fileWithEscapes.getCanonicalPath();
85-
String canonicalizedCurrentPath = currentDirectory.getCanonicalPath();
86-
return !canonicalizedTargetPath.startsWith(canonicalizedCurrentPath);
82+
private boolean isBelowOrSisterToCurrentDirectory(final String untrustedFileWithEscapes) throws IOException {
83+
// Get the absolute path of the current directory
84+
final File currentDirectory = new File("").getCanonicalFile();
85+
final Path currentPathRoot = currentDirectory.toPath();
86+
// Get the absolute path of the untrusted file
87+
final File untrustedFile = new File(currentDirectory, untrustedFileWithEscapes);
88+
final Path pathWithEscapes = untrustedFile.getCanonicalFile().toPath();
89+
return !pathWithEscapes.startsWith(currentPathRoot);
8790
}
8891

8992
private boolean isRootFileEntry(final String name) {

src/test/java/io/github/pixee/security/ZipSecurityTest.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
import static org.hamcrest.Matchers.equalTo;
55
import static org.junit.jupiter.api.Assertions.assertThrows;
66

7-
import java.io.ByteArrayInputStream;
8-
import java.io.ByteArrayOutputStream;
9-
import java.io.IOException;
10-
import java.io.InputStream;
7+
import java.io.*;
118
import java.nio.charset.StandardCharsets;
129
import java.util.zip.ZipEntry;
1310
import java.util.zip.ZipInputStream;
@@ -50,6 +47,19 @@ void it_prevents_escapes(String path) throws IOException {
5047
assertThrows(SecurityException.class, hardenedStream::getNextEntry);
5148
}
5249

50+
/**
51+
* This tests that there is no regression of CVE-2024-24569, which was a partial path traversal bypass that allowed access to the current working directory's sibling directories.
52+
*/
53+
@Test
54+
void it_prevents_sister_directory_escape() throws IOException {
55+
String currentDir = new File("").getCanonicalFile().getName();
56+
ZipEntry entry = new ZipEntry("foo/../../" + currentDir + "-other-sister-dir");
57+
InputStream is = createZipFrom(entry);
58+
59+
ZipInputStream hardenedStream = ZipSecurity.createHardenedInputStream(is);
60+
assertThrows(SecurityException.class, hardenedStream::getNextEntry);
61+
}
62+
5363
@Test
5464
void it_prevents_absolute_paths_in_zip_entries() throws IOException {
5565
ZipEntry entry = new ZipEntry("/foo.txt");

0 commit comments

Comments
 (0)