@@ -62,6 +62,7 @@ public final class FileUtil {
62
62
63
63
private static final Logger LOGGER = LogManager .logger (FileUtil .class );
64
64
private static final DirectoryStream .Filter <Path > ACCEPTING_FILTER = $ -> true ;
65
+ private static final boolean IS_WINDOWS = System .getProperty ("os.name" ).contains ("windows" );
65
66
66
67
private static final Map <String , String > ZIP_FILE_SYSTEM_PROPERTIES = Map .of (
67
68
"create" , "false" , "encoding" , "UTF-8" );
@@ -249,9 +250,9 @@ private static void extractEntry(
249
250
@ NonNull ZipEntry zipEntry ,
250
251
@ NonNull Path targetDirectory
251
252
) throws IOException {
252
- // get the target path and ensure that there is no path traversal
253
+ // checks first if the zip entry name is malicious before extracting
254
+ ensureSafeZipEntryName (zipEntry .getName ());
253
255
var file = targetDirectory .resolve (zipEntry .getName ());
254
- ensureChild (targetDirectory , file );
255
256
256
257
if (zipEntry .isDirectory ()) {
257
258
FileUtil .createDirectory (file );
@@ -330,6 +331,16 @@ public static void ensureChild(@NonNull Path root, @NonNull Path child) {
330
331
}
331
332
}
332
333
334
+ public static void ensureSafeZipEntryName (@ NonNull String name ) {
335
+ if (name .isEmpty ()
336
+ || name .startsWith ("/" )
337
+ || name .startsWith ("\\ " )
338
+ || name .contains (".." )
339
+ || (name .contains (":" ) && IS_WINDOWS )) {
340
+ throw new IllegalStateException (String .format ("zip entry name %s contains unsafe characters" , name ));
341
+ }
342
+ }
343
+
333
344
public static @ NonNull Path resolve (@ NonNull Path base , String @ NonNull ... more ) {
334
345
for (var child : more ) {
335
346
base = base .resolve (child );
0 commit comments