From 45dabaff449ca72e09eb4fb08ed05a178d936af0 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 07:54:54 -0700 Subject: [PATCH] fix(wcp): normalize separators before traversal check on unpack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older WCP files packed on Windows (before pack-side normalization was added) carry backslash separators. Normalize to '/' first so the unpack works on any platform — and so the traversal check sees a consistent canonical form (no more '\' special case). --- tools/editor/content_pack.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/editor/content_pack.cpp b/tools/editor/content_pack.cpp index 0bb6a0b3..6870e86f 100644 --- a/tools/editor/content_pack.cpp +++ b/tools/editor/content_pack.cpp @@ -181,6 +181,12 @@ bool ContentPacker::unpackZone(const std::string& wcpPath, const std::string& de } std::string path(pathLen, '\0'); in.read(path.data(), pathLen); + // Normalize separators in case this WCP was packed before the + // pack-side normalization was added (older builds emitted '\' on + // Windows). Backslash translation must happen BEFORE the + // traversal check so the absolute-path rule catches Windows + // drive letters consistently. + std::replace(path.begin(), path.end(), '\\', '/'); uint32_t dataSize; in.read(reinterpret_cast(&dataSize), 4); @@ -192,9 +198,9 @@ bool ContentPacker::unpackZone(const std::string& wcpPath, const std::string& de } // Reject path-traversal attempts. Files like "../../etc/passwd" would // write outside destDir// and clobber system files. - // Also catch Windows-style backslash traversal and absolute paths. + // (Backslashes are already normalized to '/' above.) if (path.find("..") != std::string::npos || - (!path.empty() && (path[0] == '/' || path[0] == '\\')) || + (!path.empty() && path[0] == '/') || (path.size() >= 2 && path[1] == ':')) { // C:\... drive prefix LOG_ERROR("WCP rejected suspicious path: ", path); return false;