From a0ae9725865758fc8479a5fb6b0c7763a862051c Mon Sep 17 00:00:00 2001 From: anupamme Date: Tue, 4 Aug 2026 00:19:04 +0000 Subject: [PATCH 1/3] fix: V-001 security vulnerability Automated security fix generated by OrbisAI Security --- TKLiveSync/unzip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TKLiveSync/unzip.cpp b/TKLiveSync/unzip.cpp index 84471e32..5cca4fca 100644 --- a/TKLiveSync/unzip.cpp +++ b/TKLiveSync/unzip.cpp @@ -46,7 +46,7 @@ int64_t unzip(const char* syncZipPath, const char* destination) assetFullname.append("/"); assetFullname.append(name); - strcpy(pathcopy, name); + snprintf(pathcopy, PATH_MAX, "%s", name); auto path = dirname(pathcopy); std::string dirFullname(destination); dirFullname.append("/"); From da985c208c14ed0dfe7b6bfd9f2ca843f86dba26 Mon Sep 17 00:00:00 2001 From: Anupam Mediratta Date: Thu, 6 Aug 2026 12:56:09 +0530 Subject: [PATCH 2/3] fix: eliminate fixed-size buffer in unzip.cpp to prevent path truncation Replace heap-allocated PATH_MAX buffer + strcpy/dirname with std::string find_last_of to avoid silent truncation of long ZIP entry names that could cause the directory path to diverge from assetFullname. Co-Authored-By: Claude Sonnet 4.6 --- TKLiveSync/unzip.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/TKLiveSync/unzip.cpp b/TKLiveSync/unzip.cpp index 5cca4fca..d3e4e0a2 100644 --- a/TKLiveSync/unzip.cpp +++ b/TKLiveSync/unzip.cpp @@ -1,7 +1,6 @@ #include "unzip.h" #include "libzip/zip.h" #include -#include #include #include #include @@ -36,7 +35,6 @@ int64_t unzip(const char* syncZipPath, const char* destination) struct zip_stat sb; struct zip_file* zf; char buf[65536]; - auto pathcopy = new char[PATH_MAX]; for (zip_int64_t i = 0; i < num; i++) { zip_stat_index(z, i, ZIP_STAT_MTIME, &sb); @@ -46,12 +44,15 @@ int64_t unzip(const char* syncZipPath, const char* destination) assetFullname.append("/"); assetFullname.append(name); - snprintf(pathcopy, PATH_MAX, "%s", name); - auto path = dirname(pathcopy); - std::string dirFullname(destination); - dirFullname.append("/"); - dirFullname.append(path); - mkdir_rec(dirFullname.c_str()); + std::string entryName{ name }; + auto separator = entryName.find_last_of('/'); + + if (separator != std::string::npos) { + std::string dirFullname{ destination }; + dirFullname.append("/"); + dirFullname.append(entryName.substr(0, separator)); + mkdir_rec(dirFullname.c_str()); + } zf = zip_fopen_index(z, i, 0); assert(zf != nullptr); @@ -72,7 +73,6 @@ int64_t unzip(const char* syncZipPath, const char* destination) zip_fclose(zf); } - delete[] pathcopy; zip_close(z); return num; From e473cef00c5de95501833c8ccef03660e70bcc4e Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Fri, 7 Aug 2026 18:03:30 -0700 Subject: [PATCH 3/3] fix: reject unsafe zip entry names to prevent path traversal (CWE-22) Entry names from sync.zip are untrusted, yet unzip() appended them verbatim to the destination before mkdir/fopen. Names containing ".." components or absolute paths escaped the LiveSync directory, letting a crafted archive create or overwrite files outside it (ZipSlip). Validate each entry with is_safe_entry_name() and skip entries that are absolute or contain a ".." path component. Legitimate archives extract unchanged. --- TKLiveSync/unzip.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/TKLiveSync/unzip.cpp b/TKLiveSync/unzip.cpp index d3e4e0a2..af77ba69 100644 --- a/TKLiveSync/unzip.cpp +++ b/TKLiveSync/unzip.cpp @@ -25,6 +25,26 @@ static void mkdir_rec(const char* dir) mkdir(opath, S_IRWXU); } +// ZIP entry names are untrusted input: reject absolute paths and ".." +// components so extraction can never write outside `destination`. +static bool is_safe_entry_name(const char* name) +{ + if (name == nullptr || *name == '\0' || *name == '/') + return false; + + for (const char* p = name; *p;) { + const char* component = p; + while (*p && *p != '/') + p++; + if (p - component == 2 && component[0] == '.' && component[1] == '.') + return false; + if (*p == '/') + p++; + } + + return true; +} + int64_t unzip(const char* syncZipPath, const char* destination) { int err = 0; @@ -40,6 +60,9 @@ int64_t unzip(const char* syncZipPath, const char* destination) zip_stat_index(z, i, ZIP_STAT_MTIME, &sb); auto name = sb.name; + if (!is_safe_entry_name(name)) + continue; + std::string assetFullname{ destination }; assetFullname.append("/"); assetFullname.append(name);