Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ private void addArchive(String path, File file, int type, boolean isOwn) throws
}

String name = entry.getName();
File test = new File(file.getAbsolutePath(), name);
if (!test.getCanonicalPath().startsWith(file.getCanonicalPath() + File.separator)) { // check for zip slip exploit
String normalizedName = name.replace('\\', '/');
if (normalizedName.startsWith("/") || normalizedName.startsWith(".." + "/") || normalizedName.contains("/" + ".." + "/")) { // check for zip slip exploit
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string concatenation using the + operator should be replaced with string literals for better performance and readability. Instead of ".." + "/" and "/" + ".." + "/", use "../" and "/../" directly. While the compiler may optimize simple concatenations, using string literals is clearer and avoids any potential runtime concatenation overhead.

Suggested change
if (normalizedName.startsWith("/") || normalizedName.startsWith(".." + "/") || normalizedName.contains("/" + ".." + "/")) { // check for zip slip exploit
if (normalizedName.startsWith("/") || normalizedName.startsWith("../") || normalizedName.contains("/../")) { // check for zip slip exploit

Copilot uses AI. Check for mistakes.
throw new RuntimeException("Zip entry '" + entry.getName() + "' tries to escape target directory");
}
Comment on lines +143 to 145
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The zip slip check may not catch all path traversal attempts. Consider these edge cases:

  1. Entry names that are exactly .. (would not be caught by startsWith("../"))
  2. Entry names ending with /.. like somedir/.. (would not be caught by contains("/../"))
  3. Entry names ending with .. without a slash like foo/bar.. should be allowed, but foo/bar/.. should be rejected

The check should handle these cases to be more comprehensive. Consider using a pattern that checks for .. as a complete path component, such as checking if the normalized name equals ".." or checking for the pattern "/.." at the end of the string or followed by /.

Suggested change
if (normalizedName.startsWith("/") || normalizedName.startsWith(".." + "/") || normalizedName.contains("/" + ".." + "/")) { // check for zip slip exploit
throw new RuntimeException("Zip entry '" + entry.getName() + "' tries to escape target directory");
}
if (normalizedName.startsWith("/")) { // check for zip slip exploit: absolute path
throw new RuntimeException("Zip entry '" + entry.getName() + "' tries to escape target directory");
}
for (String component : normalizedName.split("/")) { // check for zip slip exploit: parent directory traversal
if ("..".equals(component)) {
throw new RuntimeException("Zip entry '" + entry.getName() + "' tries to escape target directory");
}
}

Copilot uses AI. Check for mistakes.

Expand Down
Loading