authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2025-08-07 23:08:14+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-07 14:42:48-07:00
log242102f9d113fff321559c8645e79a29f0bdf70d
tree4c0e5787b20927009789740626d618d12b2bf809
parent6de23100352b9c94cc8c92737687091917951df3

std/zip.zig: perform backslash-to-forward-slash before isBadFilename()

Previously, when extracting a ZIP file, isBadFilename(), which is designed to reject ../ patterns to prevent directory traversal, was called before normalizing backslashes to forward slashes. This allowed path traversal sequences like ..\\..\\..\\etc\\passwd which pass validation but are then converted to ../../../etc/passwd for file extraction.

1 files changed, 3 insertions(+), 3 deletions(-)

lib/std/zip.zig+3-3
...@@ -536,9 +536,6 @@ pub const Iterator = struct {...@@ -536,9 +536,6 @@ pub const Iterator = struct {
536 @as(u64, local_header.extra_len);536 @as(u64, local_header.extra_len);
537 };537 };
538538
539 if (isBadFilename(filename))
540 return error.ZipBadFilename;
541
542 if (options.allow_backslashes) {539 if (options.allow_backslashes) {
543 std.mem.replaceScalar(u8, filename, '\\', '/');540 std.mem.replaceScalar(u8, filename, '\\', '/');
544 } else {541 } else {
...@@ -546,6 +543,9 @@ pub const Iterator = struct {...@@ -546,6 +543,9 @@ pub const Iterator = struct {
546 return error.ZipFilenameHasBackslash;543 return error.ZipFilenameHasBackslash;
547 }544 }
548545
546 if (isBadFilename(filename))
547 return error.ZipBadFilename;
548
549 // All entries that end in '/' are directories549 // All entries that end in '/' are directories
550 if (filename[filename.len - 1] == '/') {550 if (filename[filename.len - 1] == '/') {
551 if (self.uncompressed_size != 0)551 if (self.uncompressed_size != 0)