Coordinated Disclosure Timeline

Summary

Path manipulation via Zip entry files (ZipSlip)

Product

https://www.npmjs.com/package/adm-zip

Tested Version

Latest commit

Details

The extractAllTo method allows extracting all files in a zip file to a specified target folder. It tries to ensure that no files are extracted outside this folder, so even if zip file entries have paths containing .. elements the files should still end up in the target folder.

However, the code to enforce this leaves a loophole: it is possible to extract files to a different folder as long as the path of the target folder is a prefix of the path of that other folder. For example, when extracting a specially crafted zip file to target folder contents, some files could end up in a sibling folder called contents2, or some other folder whose path starts with the string contents, as shown in this example:

const AdmZip = require('adm-zip')
const zip = new AdmZip()
zip.addFile("test.txt", Buffer.from("hi"))
zip.addFile("../contents2/test2.txt", Buffer.from("there"))
zip.extractAllTo("contents") // `test.txt` is extracted to `contents`, `test2.txt` to `contents2`

Client code of adm-zip would probably assume that the check does not allow this cross-folder extraction, and might use it to extract even untrusted zip files. If an attacker can provide a crafted zip file, they might then be able to overwrite files outside the intended target folder.

In practice this is probably difficult to exploit since the paths have to match up as explained above but we think that even if this is arguably a relatively low-severity vulnerability, it is still worth fixing.

Impact

File system manipulation, Data corruption

Credit

This issue was discovered and reported by GitHub team member @max-schaefer (Max Schaefer).

Contact

You can contact the GHSL team at securitylab@github.com, please include GHSL-2020-198 in any communication regarding this issue.