Merge commit from fork

unzip: reject absolute or traversing symlink targets
This commit is contained in:
Tobias Stoeckmann authored and GitHub committed 2026-06-11 17:41:31 +02:00
commit 9bd1a06adb
1 file changed
+19 -3
+19 -3
View File
@@ -741,6 +741,14 @@ recheck:
error("close('%s')", *path);
}
static int
pathname_is_insecure(const char* pathname)
{
return (pathname[0] == '/' ||
strncmp(pathname, "../", 3) == 0 ||
strstr(pathname, "/../") != NULL);
}
/*
* Extract a zipfile entry: first perform some sanity checks to ensure
* that it is either a directory or a regular file and that the path is
@@ -760,6 +768,7 @@ static void
extract(struct archive *a, struct archive_entry *e)
{
char *pathname, *realpathname;
const char *linktarget;
mode_t filetype;
char *p, *q;
@@ -771,15 +780,22 @@ extract(struct archive *a, struct archive_entry *e)
filetype = archive_entry_filetype(e);
/* sanity checks */
if (pathname[0] == '/' ||
strncmp(pathname, "../", 3) == 0 ||
strstr(pathname, "/../") != NULL) {
if (pathname_is_insecure(pathname)) {
warningx("skipping insecure entry '%s'", pathname);
ac(archive_read_data_skip(a));
free(pathname);
return;
}
if (S_ISLNK(filetype) &&
((linktarget = archive_entry_symlink(e)) != NULL) &&
pathname_is_insecure(linktarget)) {
warningx("skipping insecure symlink '%s' to '%s'", pathname, linktarget);
ac(archive_read_data_skip(a));
free(pathname);
return;
}
/* I don't think this can happen in a zipfile.. */
if (!S_ISDIR(filetype) && !S_ISREG(filetype) && !S_ISLNK(filetype)) {
warningx("skipping non-regular entry '%s'", pathname);