Skip to content

Commit 81d6fa6

Browse files
Prevent slips, traversals and bombs
1 parent 113c952 commit 81d6fa6

File tree

1 file changed

+39
-7
lines changed

1 file changed

+39
-7
lines changed

gxcompress/src/main/java/com/genexus/compression/GXCompressor.java

+39-7
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ public class GXCompressor implements IGXCompressor {
3535
private static final String UNSUPPORTED_FORMAT = " is an unsupported format. Supported formats are zip, 7z, tar, gz and jar.";
3636
private static final String EMPTY_FILE = "The selected file is empty: ";
3737
private static final String DIRECTORY_ATTACK = "Potential directory traversal attack detected: ";
38-
private static final String MAX_FILESIZE_EXCEEDED = "The files selected for compression exceed the maximum permitted file size of ";
38+
private static final String MAX_FILESIZE_EXCEEDED = "The file(s) selected for (de)compression exceed the maximum permitted file size of ";
39+
private static final String TOO_MANY_FILES = "Too many files have been added for (de)compression. Maximum allowed is ";
40+
private static final String ZIP_SLIP_DETECTED = "Zip slip or path traversal attack detected in archive: ";
41+
private static final int MAX_FILES_ALLOWED = 1000;
3942

4043
private static void storageMessages(String error, GXBaseCollection<SdtMessages_Message> messages) {
4144
try {
@@ -55,6 +58,12 @@ public static Boolean compress(ArrayList<String> files, String path, long maxCom
5558
storageMessages(NO_FILES_ADDED, messages[0]);
5659
return false;
5760
}
61+
if(maxCombinedFileSize > -1 && files.size() > MAX_FILES_ALLOWED){
62+
log.error(TOO_MANY_FILES + MAX_FILES_ALLOWED);
63+
storageMessages(TOO_MANY_FILES + MAX_FILES_ALLOWED, messages[0]);
64+
files.clear();
65+
return false;
66+
}
5867
long totalSize = 0;
5968
File[] toCompress = new File[files.size()];
6069
int index = 0;
@@ -67,18 +76,18 @@ public static Boolean compress(ArrayList<String> files, String path, long maxCom
6776
storageMessages(FILE_NOT_EXISTS + filePath, messages[0]);
6877
continue;
6978
}
70-
if (normalizedPath.contains(File.separator + ".." + File.separator) ||
71-
normalizedPath.endsWith(File.separator + "..") ||
72-
normalizedPath.startsWith(".." + File.separator)) {
79+
if (!normalizedPath.equals(file.getAbsolutePath())) {
7380
log.error(DIRECTORY_ATTACK + "{}", filePath);
7481
storageMessages(DIRECTORY_ATTACK + filePath, messages[0]);
7582
return false;
7683
}
7784
long fileSize = file.length();
7885
totalSize += fileSize;
79-
if (totalSize > maxCombinedFileSize && maxCombinedFileSize > -1) {
80-
log.error(MAX_FILESIZE_EXCEEDED + "{}", maxCombinedFileSize);
86+
if (maxCombinedFileSize > -1 && totalSize > maxCombinedFileSize) {
87+
log.error(MAX_FILESIZE_EXCEEDED + maxCombinedFileSize);
8188
storageMessages(MAX_FILESIZE_EXCEEDED + maxCombinedFileSize, messages[0]);
89+
toCompress = null;
90+
files.clear();
8291
return false;
8392
}
8493
toCompress[index++] = file;
@@ -133,6 +142,29 @@ public static Boolean decompress(String file, String path, GXBaseCollection<SdtM
133142
storageMessages(EMPTY_FILE + file, messages[0]);
134143
return false;
135144
}
145+
try {
146+
int fileCount = CompressionUtils.countArchiveEntries(toCompress);
147+
if (fileCount > MAX_FILES_ALLOWED) {
148+
log.error(TOO_MANY_FILES + fileCount);
149+
storageMessages(TOO_MANY_FILES + fileCount, messages[0]);
150+
return false;
151+
}
152+
} catch (Exception e) {
153+
log.error("Error counting archive entries for file: {}", file, e);
154+
storageMessages("Error counting archive entries for file: " + file, messages[0]);
155+
return false;
156+
}
157+
try {
158+
if (!CompressionUtils.isArchiveSafe(toCompress, path)) {
159+
log.error(ZIP_SLIP_DETECTED + file);
160+
storageMessages(ZIP_SLIP_DETECTED + file, messages[0]);
161+
return false;
162+
}
163+
} catch (Exception e) {
164+
log.error("Error checking archive safety for file: {}", file, e);
165+
storageMessages("Error checking archive safety for file: " + file, messages[0]);
166+
return false;
167+
}
136168
String extension = getExtension(toCompress.getName());
137169
try {
138170
switch (extension.toLowerCase()) {
@@ -636,4 +668,4 @@ private static void decompressJar(File archive, String directory) throws IOExcep
636668
}
637669
}
638670
}
639-
}
671+
}

0 commit comments

Comments
 (0)