diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f9a7e491bd3af..3c0f7e8a0221d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,7 +32,8 @@ release.
-18.20.1
+18.20.2
+18.20.1
18.20.0
18.19.1
18.19.0
diff --git a/benchmark/_http-benchmarkers.js b/benchmark/_http-benchmarkers.js
index ae5429fa721750..4eba83eccb58f0 100644
--- a/benchmark/_http-benchmarkers.js
+++ b/benchmark/_http-benchmarkers.js
@@ -12,11 +12,16 @@ exports.PORT = Number(process.env.PORT) || 12346;
class AutocannonBenchmarker {
constructor() {
+ const shell = (process.platform === 'win32');
this.name = 'autocannon';
- this.executable =
- process.platform === 'win32' ? 'autocannon.cmd' : 'autocannon';
- const result = child_process.spawnSync(this.executable, ['-h']);
- this.present = !(result.error && result.error.code === 'ENOENT');
+ this.opts = { shell };
+ this.executable = shell ? 'autocannon.cmd' : 'autocannon';
+ const result = child_process.spawnSync(this.executable, ['-h'], this.opts);
+ if (shell) {
+ this.present = (result.status === 0);
+ } else {
+ this.present = !(result.error && result.error.code === 'ENOENT');
+ }
}
create(options) {
@@ -27,11 +32,15 @@ class AutocannonBenchmarker {
'-n',
];
for (const field in options.headers) {
- args.push('-H', `${field}=${options.headers[field]}`);
+ if (this.opts.shell) {
+ args.push('-H', `'${field}=${options.headers[field]}'`);
+ } else {
+ args.push('-H', `${field}=${options.headers[field]}`);
+ }
}
const scheme = options.scheme || 'http';
args.push(`${scheme}://127.0.0.1:${options.port}${options.path}`);
- const child = child_process.spawn(this.executable, args);
+ const child = child_process.spawn(this.executable, args, this.opts);
return child;
}
diff --git a/doc/changelogs/CHANGELOG_V18.md b/doc/changelogs/CHANGELOG_V18.md
index 1c61f784ddca03..678527839e56ac 100644
--- a/doc/changelogs/CHANGELOG_V18.md
+++ b/doc/changelogs/CHANGELOG_V18.md
@@ -9,6 +9,7 @@
|
+18.20.2
18.20.1
18.20.0
18.19.1
@@ -66,6 +67,20 @@
* [io.js](CHANGELOG_IOJS.md)
* [Archive](CHANGELOG_ARCHIVE.md)
+
+
+## 2024-04-10, Version 18.20.2 'Hydrogen' (LTS), @RafaelGSS
+
+This is a security release.
+
+### Notable Changes
+
+* CVE-2024-27980 - Command injection via args parameter of `child_process.spawn` without shell option enabled on Windows
+
+### Commits
+
+* \[[`6627222409`](https://github.com/nodejs/node/commit/6627222409)] - **src**: disallow direct .bat and .cmd file spawning (Ben Noordhuis) [nodejs-private/node-private#564](https://github.com/nodejs-private/node-private/pull/564)
+
## 2024-04-03, Version 18.20.1 'Hydrogen' (LTS), @RafaelGSS
diff --git a/src/node_revert.h b/src/node_revert.h
index 071673e1290638..e975982bcb5af6 100644
--- a/src/node_revert.h
+++ b/src/node_revert.h
@@ -16,7 +16,8 @@
namespace node {
#define SECURITY_REVERSIONS(XX) \
- XX(CVE_2023_46809, "CVE-2023-46809", "Marvin attack on PKCS#1 padding")
+ XX(CVE_2023_46809, "CVE-2023-46809", "Marvin attack on PKCS#1 padding") \
+ XX(CVE_2024_27980, "CVE-2024-27980", "Unsafe Windows batch file execution")
enum reversion {
#define V(code, ...) SECURITY_REVERT_##code,
diff --git a/src/node_version.h b/src/node_version.h
index 6973a3d0fd8b12..59377f7778f2c6 100644
--- a/src/node_version.h
+++ b/src/node_version.h
@@ -24,7 +24,7 @@
#define NODE_MAJOR_VERSION 18
#define NODE_MINOR_VERSION 20
-#define NODE_PATCH_VERSION 1
+#define NODE_PATCH_VERSION 2
#define NODE_VERSION_IS_LTS 1
#define NODE_VERSION_LTS_CODENAME "Hydrogen"
diff --git a/src/process_wrap.cc b/src/process_wrap.cc
index ffa5dbd1306a6d..4446f7a01c583c 100644
--- a/src/process_wrap.cc
+++ b/src/process_wrap.cc
@@ -147,6 +147,7 @@ class ProcessWrap : public HandleWrap {
Local context = env->context();
ProcessWrap* wrap;
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
+ int err = 0;
Local |