From 39f207023a0f3d4cf3d54f2983da5f775d22e8ca Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Tue, 21 May 2024 11:10:12 -0300 Subject: [PATCH] src: handle permissive extension on cmd check PR-URL: https://github.com/nodejs-private/node-private/pull/596 Reviewed-By: Michael Dawson Reviewed-By: Matteo Collina CVE-ID: CVE-2024-36138 --- src/util-inl.h | 18 +++++++++++++++--- ...t-child-process-spawn-windows-batch-file.js | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/util-inl.h b/src/util-inl.h index 88d0cfee7f2..86e6aaaec9c 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -27,6 +27,7 @@ #include #include #include +#include // NOLINT(build/c++11) #include "node_revert.h" #include "util.h" @@ -543,9 +544,20 @@ bool IsWindowsBatchFile(const char* filename) { #else static constexpr bool kIsWindows = false; #endif // _WIN32 - if (kIsWindows) - if (const char* p = strrchr(filename, '.')) - return StringEqualNoCase(p, ".bat") || StringEqualNoCase(p, ".cmd"); + if (kIsWindows) { + std::string file_with_extension = filename; + // Regex to match the last extension part after the last dot, ignoring + // trailing spaces and dots + std::regex extension_regex(R"(\.([a-zA-Z0-9]+)\s*[\.\s]*$)"); + std::smatch match; + std::string extension; + + if (std::regex_search(file_with_extension, match, extension_regex)) { + extension = ToLower(match[1].str()); + } + + return !extension.empty() && (extension == "cmd" || extension == "bat"); + } return false; } diff --git a/test/parallel/test-child-process-spawn-windows-batch-file.js b/test/parallel/test-child-process-spawn-windows-batch-file.js index 242f2d2d1bb..4d305743606 100644 --- a/test/parallel/test-child-process-spawn-windows-batch-file.js +++ b/test/parallel/test-child-process-spawn-windows-batch-file.js @@ -23,8 +23,8 @@ const expectedCode = isWindows ? 'EINVAL' : 'ENOENT'; const expectedStatus = isWindows ? 1 : 127; const suffixes = - 'BAT bAT BaT baT BAt bAt Bat bat CMD cMD CmD cmD CMd cMd Cmd cmd' - .split(' '); + 'BAT|bAT|BaT|baT|BAt|bAt|Bat|bat|CMD|cMD|CmD|cmD|CMd|cMd|Cmd|cmd|cmd |cmd .|cmd ....' + .split('|'); function testExec(filename) { return new Promise((resolve) => {