-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(CodeQL) Fixed finding: "Arbitrary file access during archive extraction ("Zip Slip") " #2344
Conversation
…ion ("Zip Slip") "
@@ -105,7 +105,7 @@ | |||
new ByteArrayInputStream(Files.readAllBytes(zipFilePath)))) { | |||
ZipEntry entry = zipIn.getNextEntry(); | |||
while (entry != null) { | |||
Path filePath = tempUnzippedDir.resolve(entry.getName()); | |||
Path filePath = tempUnzippedDir.resolve(sanitizeZipFilename(entry.getName())); |
Check failure
Code scanning / CodeQL
Arbitrary file access during archive extraction ("Zip Slip") High
file system operation
Unsanitized archive entry, which may contain '..', is used in a
file system operation
Unsanitized archive entry, which may contain '..', is used in a
file system operation
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI about 2 months ago
To fix the problem, we need to ensure that the output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. This can be achieved by verifying that the normalized full path of the output file starts with a prefix that matches the destination directory. We will use java.nio.file.Path.normalize()
and java.nio.file.Path.startsWith(..)
for this purpose.
- Modify the
sanitizeHtmlFilesInZip
method to include a check that ensures the normalized path of the extracted file starts with the temporary directory path. - Update the
sanitizeZipFilename
method to be more robust in handling directory traversal sequences.
-
Copy modified lines R108-R111 -
Copy modified lines R252-R254
@@ -107,3 +107,6 @@ | ||
while (entry != null) { | ||
Path filePath = tempUnzippedDir.resolve(sanitizeZipFilename(entry.getName())); | ||
Path filePath = tempUnzippedDir.resolve(sanitizeZipFilename(entry.getName())).normalize(); | ||
if (!filePath.startsWith(tempUnzippedDir)) { | ||
throw new IOException("Bad zip entry: " + entry.getName()); | ||
} | ||
if (!entry.isDirectory()) { | ||
@@ -248,4 +251,5 @@ | ||
} | ||
while (entryName.contains("../") || entryName.contains("..\\")) { | ||
entryName = entryName.replace("../", "").replace("..\\", ""); | ||
entryName = entryName.replace("\\", "/"); | ||
while (entryName.contains("../")) { | ||
entryName = entryName.replace("../", ""); | ||
} |
@@ -175,7 +175,7 @@ | |||
ZipSecurity.createHardenedInputStream(new ByteArrayInputStream(fileBytes))) { | |||
ZipEntry entry = zipIn.getNextEntry(); | |||
while (entry != null) { | |||
Path filePath = tempDirectory.resolve(entry.getName()); | |||
Path filePath = tempDirectory.resolve(sanitizeZipFilename(entry.getName())); |
Check failure
Code scanning / CodeQL
Arbitrary file access during archive extraction ("Zip Slip") High
file system operation
Unsanitized archive entry, which may contain '..', is used in a
file system operation
Unsanitized archive entry, which may contain '..', is used in a
file system operation
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI about 2 months ago
To fix the problem, we need to ensure that the output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. This can be achieved by verifying that the normalized full path of the output file starts with a prefix that matches the destination directory. We will use java.nio.file.Path.normalize()
and java.nio.file.Path.startsWith(..)
for this purpose.
- Modify the
unzipAndGetMainHtml
method to validate the constructed file paths. - Ensure that the
sanitizeZipFilename
method is robust enough to handle all potential directory traversal sequences.
-
Copy modified lines R178-R181
@@ -177,3 +177,6 @@ | ||
while (entry != null) { | ||
Path filePath = tempDirectory.resolve(sanitizeZipFilename(entry.getName())); | ||
Path filePath = tempDirectory.resolve(sanitizeZipFilename(entry.getName())).normalize(); | ||
if (!filePath.startsWith(tempDirectory)) { | ||
throw new IOException("Bad zip entry: " + entry.getName()); | ||
} | ||
if (entry.isDirectory()) { |
Remediation
This change fixes "Arbitrary file access during archive extraction ("Zip Slip")
" (id = zipslip) identified by CodeQL.
Details
This change fixes instances of ZipInputStream to protect against malicious entries that attempt to escape their "file root" and overwrite other files on the running filesystem.
Normally, when you're using
ZipInputStream
it's because you're processing zip files. That code might look like this:This looks fine when it encounters a normal zip entry within a zip file, looking something like this pseudo-data:
However, there's nothing to prevent an attacker from sending an evil entry in the zip that looks more like this:
Yes, in the above code, which looks like every piece of zip-processing code you can find on the Internet, attackers could overwrite any files to which the application has access. This rule replaces the standard
ZipInputStream
with a hardened subclass which prevents access to entry paths that attempt to traverse directories above the current directory (which no normal zip file should ever do.) Our changes end up looking something like this:More reading
🧚🤖 Powered by Pixeebot
Feedback | Community | Docs | Codemod ID: codeql:java/zipslip