Fix CVE-2022-32212,CVE-2022-32213,CVE-2022-32214,CVE-2022-32215,CVE-2022-25881,CVE-2023-23918,CVE-2023-23920,CVE-2023-30589,CVE-2023-30590,CVE-2023-30581,CVE-2023-32002,CVE-2023-32006,CVE-2023-32559,CVE-2022-35256

This commit is contained in:
wk333 2023-08-29 17:18:30 +08:00
parent 950d1bc7c3
commit b06001d17b
14 changed files with 8948 additions and 91 deletions

34
CVE-2022-25881.patch Normal file
View File

@ -0,0 +1,34 @@
Index: node-v14.21.3/deps/npm/node_modules/http-cache-semantics/node4/index.js
===================================================================
--- node-v14.21.3.orig/deps/npm/node_modules/http-cache-semantics/node4/index.js
+++ node-v14.21.3/deps/npm/node_modules/http-cache-semantics/node4/index.js
@@ -21,7 +21,7 @@ function parseCacheControl(header) {
// TODO: When there is more than one value present for a given directive (e.g., two Expires header fields, multiple Cache-Control: max-age directives),
// the directive's value is considered invalid. Caches are encouraged to consider responses that have invalid freshness information to be stale
- var parts = header.trim().split(/\s*,\s*/); // TODO: lame parsing
+ var parts = header.trim().split(/,/); // TODO: lame parsing
for (var _iterator = parts, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
@@ -36,11 +36,11 @@ function parseCacheControl(header) {
var part = _ref;
- var _part$split = part.split(/\s*=\s*/, 2),
+ var _part$split = part.split(/=/, 2),
k = _part$split[0],
v = _part$split[1];
- cc[k] = v === undefined ? true : v.replace(/^"|"$/g, ''); // TODO: lame unquoting
+ cc[k.trim()] = v === undefined ? true : v.trim().replace(/^"|"$/g, ''); // TODO: lame unquoting
}
return cc;
@@ -556,4 +556,4 @@ module.exports = function () {
};
return CachePolicy;
-}();
\ No newline at end of file
+}();

View File

@ -1,7 +1,8 @@
From 1aa5036c31ac2a9b2a2528af454675ad412f1464 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= <tniessen@tnie.de>
Date: Fri, 27 May 2022 21:18:49 +0000
Subject: [PATCH] src: fix IPv4 validation in inspector_socket
commit 1aa5036c31ac2a9b2a2528af454675ad412f1464
Author: Tobias Nießen <tniessen@tnie.de>
Date: Fri May 27 21:18:49 2022 +0000
src: fix IPv4 validation in inspector_socket
Co-authored-by: RafaelGSS <rafael.nunu@hotmail.com>
@ -9,13 +10,9 @@ Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs-private/node-private/pull/320
CVE-ID: CVE-2022-32212
---
src/inspector_socket.cc | 18 +++++--
test/cctest/test_inspector_socket.cc | 74 ++++++++++++++++++++++++++++
2 files changed, 87 insertions(+), 5 deletions(-)
diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc
index 1650c3fe01de..79b50e6a452d 100644
index 1650c3fe01..79b50e6a45 100644
--- a/src/inspector_socket.cc
+++ b/src/inspector_socket.cc
@@ -164,14 +164,22 @@ static std::string TrimPort(const std::string& host) {
@ -47,7 +44,7 @@ index 1650c3fe01de..79b50e6a452d 100644
// Constants for hybi-10 frame format.
diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc
index dc8cd962141e..c740d961d9b7 100644
index dc8cd96214..c740d961d9 100644
--- a/test/cctest/test_inspector_socket.cc
+++ b/test/cctest/test_inspector_socket.cc
@@ -851,4 +851,78 @@ TEST_F(InspectorSocketTest, HostCheckedForUPGRADE) {

File diff suppressed because it is too large Load Diff

1581
CVE-2022-35256.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +0,0 @@
From b358fb27a4253c6827378a64163448c04301e19c Mon Sep 17 00:00:00 2001
From: RafaelGSS <rafael.nunu@hotmail.com>
Date: Wed, 13 Jul 2022 13:20:22 -0300
Subject: [PATCH] src: fix IPv4 non routable validation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
PR-URL: https://github.com/nodejs-private/node-private/pull/337
CVE-ID: CVE-2022-32212, CVE-2018-7160
---
src/inspector_socket.cc | 1 +
test/cctest/test_inspector_socket.cc | 8 ++++++++
2 files changed, 9 insertions(+)
diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc
index 79b50e6a452d..ab1cdf1fa5bd 100644
--- a/src/inspector_socket.cc
+++ b/src/inspector_socket.cc
@@ -164,6 +164,7 @@ static std::string TrimPort(const std::string& host) {
static bool IsIPAddress(const std::string& host) {
if (host.length() >= 4 && host.front() == '[' && host.back() == ']')
return true;
+ if (host.front() == '0') return false;
uint_fast16_t accum = 0;
uint_fast8_t quads = 0;
bool empty = true;
diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc
index c740d961d9b7..6ae92c4b27e2 100644
--- a/test/cctest/test_inspector_socket.cc
+++ b/test/cctest/test_inspector_socket.cc
@@ -925,4 +925,12 @@ TEST_F(InspectorSocketTest, HostIpTooManyOctetsChecked) {
expect_handshake_failure();
}
+TEST_F(InspectorSocketTest, HostIPNonRoutable) {
+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
+ "Host: 0.0.0.0:9229\r\n\r\n";
+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
+ INVALID_HOST_IP_REQUEST.length());
+ expect_handshake_failure();
+}
+
} // anonymous namespace

View File

@ -19,11 +19,11 @@ Reviewed-by: Rich Trott <rtrott@gmail.com>
test/cctest/test_inspector_socket.cc | 80 ++++++++++++++++++++++++++++
2 files changed, 142 insertions(+), 16 deletions(-)
diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc
index 8cabdaec2821..a28bd557c8ab 100644
--- a/src/inspector_socket.cc
+++ b/src/inspector_socket.cc
@@ -6,6 +6,7 @@
Index: node-v12.22.12/src/inspector_socket.cc
===================================================================
--- node-v12.22.12.orig/src/inspector_socket.cc
+++ node-v12.22.12/src/inspector_socket.cc
@@ -10,6 +10,7 @@
#include "openssl/sha.h" // Sha-1 hash
@ -31,13 +31,12 @@ index 8cabdaec2821..a28bd557c8ab 100644
#include <cstring>
#include <map>
@@ -162,25 +163,70 @@ static std::string TrimPort(const std::string& host) {
@@ -166,24 +167,70 @@ static std::string TrimPort(const std::s
}
static bool IsIPAddress(const std::string& host) {
- if (host.length() >= 4 && host.front() == '[' && host.back() == ']')
- return true;
- if (host.front() == '0') return false;
- uint_fast16_t accum = 0;
- uint_fast8_t quads = 0;
- bool empty = true;
@ -118,11 +117,11 @@ index 8cabdaec2821..a28bd557c8ab 100644
}
// Constants for hybi-10 frame format.
diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc
index 6ae92c4b27e2..b351a23002c9 100644
--- a/test/cctest/test_inspector_socket.cc
+++ b/test/cctest/test_inspector_socket.cc
@@ -925,6 +925,54 @@ TEST_F(InspectorSocketTest, HostIpTooManyOctetsChecked) {
Index: node-v12.22.12/test/cctest/test_inspector_socket.cc
===================================================================
--- node-v12.22.12.orig/test/cctest/test_inspector_socket.cc
+++ node-v12.22.12/test/cctest/test_inspector_socket.cc
@@ -925,4 +925,85 @@ TEST_F(InspectorSocketTest, HostIpTooMan
expect_handshake_failure();
}
@ -174,13 +173,7 @@ index 6ae92c4b27e2..b351a23002c9 100644
+ expect_handshake_failure();
+}
+
TEST_F(InspectorSocketTest, HostIPNonRoutable) {
const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
"Host: 0.0.0.0:9229\r\n\r\n";
@@ -933,4 +981,36 @@ TEST_F(InspectorSocketTest, HostIPNonRoutable) {
expect_handshake_failure();
}
+
+TEST_F(InspectorSocketTest, HostIPv6NonRoutable) {
+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
+ "Host: [::]:9229\r\n\r\n";

699
CVE-2023-23918.patch Normal file
View File

@ -0,0 +1,699 @@
commit f7892c16be6507e26c2ae478c261fa3fa2d84f52
Author: RafaelGSS <rafael.nunu@hotmail.com>
Date: Mon Feb 13 15:41:30 2023 -0300
lib: makeRequireFunction patch when experimental policy
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/373
Refs: https://hackerone.com/bugs?subject=nodejs&report_id=1747642
CVE-ID: CVE-2023-23918
PR-URL: https://github.com/nodejs-private/node-private/pull/358
Reviewed-by: Bradley Farias <bradley.meck@gmail.com>
Reviewed-by: Michael Dawson <midawson@redhat.com>
commit 83975b7fb463e29c92c8e83693b725e269cee149
Author: RafaelGSS <rafael.nunu@hotmail.com>
Date: Tue Oct 25 00:23:27 2022 -0300
policy: makeRequireFunction on mainModule.require
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
Co-authored-by: Bradley Farias <bradley.meck@gmail.com>
Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/373
Refs: https://hackerone.com/bugs?subject=nodejs&report_id=1747642
CVE-ID: CVE-2023-23918
PR-URL: https://github.com/nodejs-private/node-private/pull/358
Reviewed-by: Bradley Farias <bradley.meck@gmail.com>
Reviewed-by: Michael Dawson <midawson@redhat.com>
commit fa115ee8ac32883c96df4a93fafb600bd665a5aa
Author: Antoine du Hamel <duhamelantoine1995@gmail.com>
Date: Fri Aug 5 00:41:48 2022 +0200
module: protect against prototype mutation
Ensures that mutating the `Object` prototype does not influence the
parsing of `package.json` files.
Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/373
PR-URL: https://github.com/nodejs/node/pull/44007
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Index: node-v12.22.12/lib/internal/modules/cjs/helpers.js
===================================================================
--- node-v12.22.12.orig/lib/internal/modules/cjs/helpers.js
+++ node-v12.22.12/lib/internal/modules/cjs/helpers.js
@@ -5,6 +5,7 @@ const {
SafeMap,
} = primordials;
const {
+ ERR_INVALID_ARG_TYPE,
ERR_MANIFEST_DEPENDENCY_MISSING,
ERR_UNKNOWN_BUILTIN_MODULE
} = require('internal/errors').codes;
@@ -14,11 +15,22 @@ const { validateString } = require('inte
const path = require('path');
const { pathToFileURL, fileURLToPath } = require('internal/url');
const { URL } = require('url');
+const { setOwnProperty } = require('internal/util');
+
+const {
+ require_private_symbol,
+} = internalBinding('util');
let debug = require('internal/util/debuglog').debuglog('module', (fn) => {
debug = fn;
});
+// TODO: Use this set when resolving pkg#exports conditions in loader.js.
+const cjsConditions = [
+ 'require',
+ 'node',
+];
+
function loadNativeModule(filename, request) {
const mod = NativeModule.map.get(filename);
if (mod) {
@@ -28,20 +40,31 @@ function loadNativeModule(filename, requ
}
}
+let $Module = null;
+function lazyModule() {
+ $Module = $Module || require('internal/modules/cjs/loader').Module;
+ return $Module;
+}
+
// Invoke with makeRequireFunction(module) where |module| is the Module object
// to use as the context for the require() function.
// Use redirects to set up a mapping from a policy and restrict dependencies
const urlToFileCache = new SafeMap();
function makeRequireFunction(mod, redirects) {
- const Module = mod.constructor;
+ // lazy due to cycle
+ const Module = lazyModule();
+ if (mod instanceof Module !== true) {
+ throw new ERR_INVALID_ARG_TYPE('mod', 'Module', mod);
+ }
let require;
if (redirects) {
const { resolve, reaction } = redirects;
const id = mod.filename || mod.id;
+ const conditions = cjsConditions;
require = function require(path) {
let missing = true;
- const destination = resolve(path);
+ const destination = resolve(path, conditions);
if (destination === true) {
missing = false;
} else if (destination) {
@@ -61,17 +84,17 @@ function makeRequireFunction(mod, redire
filepath = fileURLToPath(destination);
urlToFileCache.set(href, filepath);
}
- return mod.require(filepath);
+ return mod[require_private_symbol](mod, filepath);
}
}
if (missing) {
- reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(id, path));
+ reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(id, path, ArrayPrototypeJoin([...conditions], ', ')));
}
- return mod.require(path);
+ return mod[require_private_symbol](mod, path);
};
} else {
require = function require(path) {
- return mod.require(path);
+ return mod[require_private_symbol](mod, path);
};
}
@@ -89,7 +112,7 @@ function makeRequireFunction(mod, redire
resolve.paths = paths;
- require.main = process.mainModule;
+ setOwnProperty(require, 'main', process.mainModule);
// Enable support to add extra extension types.
require.extensions = Module._extensions;
Index: node-v12.22.12/lib/internal/modules/cjs/loader.js
===================================================================
--- node-v12.22.12.orig/lib/internal/modules/cjs/loader.js
+++ node-v12.22.12/lib/internal/modules/cjs/loader.js
@@ -59,7 +59,7 @@ const {
rekeySourceMap
} = require('internal/source_map/source_map_cache');
const { pathToFileURL, fileURLToPath, isURLInstance } = require('internal/url');
-const { deprecate } = require('internal/util');
+const { deprecate, filterOwnProperties, setOwnProperty } = require('internal/util');
const vm = require('vm');
const assert = require('internal/assert');
const fs = require('fs');
@@ -70,6 +70,9 @@ const { internalModuleStat } = internalB
const packageJsonReader = require('internal/modules/package_json_reader');
const { safeGetenv } = internalBinding('credentials');
const {
+ require_private_symbol,
+} = internalBinding('util');
+const {
makeRequireFunction,
normalizeReferrerURL,
stripBOM,
@@ -120,6 +123,20 @@ const relativeResolveCache = ObjectCreat
let requireDepth = 0;
let statCache = null;
+function internalRequire(module, id) {
+ validateString(id, 'id');
+ if (id === '') {
+ throw new ERR_INVALID_ARG_VALUE('id', id,
+ 'must be a non-empty string');
+ }
+ requireDepth++;
+ try {
+ return Module._load(id, module, /* isMain */ false);
+ } finally {
+ requireDepth--;
+ }
+}
+
function stat(filename) {
filename = path.toNamespacedPath(filename);
if (statCache !== null) {
@@ -140,12 +157,21 @@ function updateChildren(parent, child, s
function Module(id = '', parent) {
this.id = id;
this.path = path.dirname(id);
- this.exports = {};
+ setOwnProperty(this, 'exports', {});
this.parent = parent;
updateChildren(parent, this, false);
this.filename = null;
this.loaded = false;
this.children = [];
+ let redirects;
+ if (manifest) {
+ const moduleURL = pathToFileURL(id);
+ redirects = manifest.getRedirector(moduleURL);
+ }
+ setOwnProperty(this, 'require', makeRequireFunction(this, redirects));
+ // Loads a module at the given file path. Returns that module's
+ // `exports` property.
+ this[require_private_symbol] = internalRequire;
}
const builtinModules = [];
@@ -242,14 +268,13 @@ function readPackage(requestPath) {
}
try {
- const parsed = JSONParse(json);
- const filtered = {
- name: parsed.name,
- main: parsed.main,
- exports: parsed.exports,
- imports: parsed.imports,
- type: parsed.type
- };
+ const filtered = filterOwnProperties(JSONParse(json), [
+ 'name',
+ 'main',
+ 'exports',
+ 'imports',
+ 'type',
+ ]);
packageJsonCache.set(jsonPath, filtered);
return filtered;
} catch (e) {
@@ -684,6 +709,7 @@ Module._load = function(request, parent,
if (isMain) {
process.mainModule = module;
+ setOwnProperty(module.require, 'main', process.mainModule);
module.id = '.';
}
@@ -873,24 +899,6 @@ Module.prototype.load = function(filenam
ESMLoader.cjsCache.set(this, exports);
};
-
-// Loads a module at the given file path. Returns that module's
-// `exports` property.
-Module.prototype.require = function(id) {
- validateString(id, 'id');
- if (id === '') {
- throw new ERR_INVALID_ARG_VALUE('id', id,
- 'must be a non-empty string');
- }
- requireDepth++;
- try {
- return Module._load(id, this, /* isMain */ false);
- } finally {
- requireDepth--;
- }
-};
-
-
// Resolved path to process.argv[1] will be lazily placed here
// (needed for setting breakpoint when called with --inspect-brk)
let resolvedArgv;
@@ -952,10 +960,9 @@ function wrapSafe(filename, content, cjs
// Returns exception, if any.
Module.prototype._compile = function(content, filename) {
let moduleURL;
- let redirects;
if (manifest) {
moduleURL = pathToFileURL(filename);
- redirects = manifest.getRedirector(moduleURL);
+ manifest.getRedirector(moduleURL);
manifest.assertIntegrity(moduleURL, content);
}
@@ -986,7 +993,6 @@ Module.prototype._compile = function(con
}
}
const dirname = path.dirname(filename);
- const require = makeRequireFunction(this, redirects);
let result;
const exports = this.exports;
const thisValue = exports;
@@ -994,9 +1000,9 @@ Module.prototype._compile = function(con
if (requireDepth === 0) statCache = new Map();
if (inspectorWrapper) {
result = inspectorWrapper(compiledWrapper, thisValue, exports,
- require, module, filename, dirname);
+ module.require, module, filename, dirname);
} else {
- result = compiledWrapper.call(thisValue, exports, require, module,
+ result = compiledWrapper.call(thisValue, exports, module.require, module,
filename, dirname);
}
hasLoadedAnyUserCJSModule = true;
@@ -1038,7 +1044,7 @@ Module._extensions['.json'] = function(m
}
try {
- module.exports = JSONParse(stripBOM(content));
+ setOwnProperty(module, 'exports', JSONParse(stripBOM(content)));
} catch (err) {
err.message = filename + ': ' + err.message;
throw err;
@@ -1144,7 +1150,7 @@ Module._preloadModules = function(reques
}
}
for (let n = 0; n < requests.length; n++)
- parent.require(requests[n]);
+ internalRequire(parent, requests[n]);
};
Module.syncBuiltinESMExports = function syncBuiltinESMExports() {
@@ -1155,5 +1161,14 @@ Module.syncBuiltinESMExports = function
}
};
+ObjectDefineProperty(Module.prototype, 'constructor', {
+ __proto__: null,
+ get: function() {
+ return policy ? undefined : Module;
+ },
+ configurable: false,
+ enumerable: false,
+});
+
// Backwards compatibility
Module.Module = Module;
Index: node-v12.22.12/lib/internal/util.js
===================================================================
--- node-v12.22.12.orig/lib/internal/util.js
+++ node-v12.22.12/lib/internal/util.js
@@ -11,6 +11,7 @@ const {
ObjectGetOwnPropertyDescriptor,
ObjectGetOwnPropertyDescriptors,
ObjectGetPrototypeOf,
+ ObjectPrototypeHasOwnProperty,
ObjectSetPrototypeOf,
Promise,
ReflectConstruct,
@@ -404,6 +405,35 @@ function sleep(msec) {
_sleep(msec);
}
+function filterOwnProperties(source, keys) {
+ const filtered = ObjectCreate(null);
+ for (let i = 0; i < keys.length; i++) {
+ const key = keys[i];
+ if (ObjectPrototypeHasOwnProperty(source, key)) {
+ filtered[key] = source[key];
+ }
+ }
+
+ return filtered;
+}
+
+/**
+ * Mimics `obj[key] = value` but ignoring potential prototype inheritance.
+ * @param {any} obj
+ * @param {string} key
+ * @param {any} value
+ * @returns {any}
+ */
+function setOwnProperty(obj, key, value) {
+ return ObjectDefineProperty(obj, key, {
+ __proto__: null,
+ configurable: true,
+ enumerable: true,
+ value,
+ writable: true,
+ });
+}
+
module.exports = {
assertCrypto,
cachedResult,
@@ -413,6 +443,7 @@ module.exports = {
deprecate,
emitExperimentalWarning,
filterDuplicateStrings,
+ filterOwnProperties,
getConstructorOf,
getSystemErrorName,
isError,
@@ -435,5 +466,6 @@ module.exports = {
// Used by the buffer module to capture an internal reference to the
// default isEncoding implementation, just in case userland overrides it.
kIsEncodingSymbol: Symbol('kIsEncodingSymbol'),
- kVmBreakFirstLineSymbol: Symbol('kVmBreakFirstLineSymbol')
+ kVmBreakFirstLineSymbol: Symbol('kVmBreakFirstLineSymbol'),
+ setOwnProperty,
};
Index: node-v12.22.12/test/common/fixtures.js
===================================================================
--- node-v12.22.12.orig/test/common/fixtures.js
+++ node-v12.22.12/test/common/fixtures.js
@@ -3,6 +3,7 @@
const path = require('path');
const fs = require('fs');
+const { pathToFileURL } = require('url');
const fixturesDir = path.join(__dirname, '..', 'fixtures');
@@ -10,6 +11,10 @@ function fixturesPath(...args) {
return path.join(fixturesDir, ...args);
}
+function fixturesFileURL(...args) {
+ return pathToFileURL(fixturesPath(...args));
+}
+
function readFixtureSync(args, enc) {
if (Array.isArray(args))
return fs.readFileSync(fixturesPath(...args), enc);
@@ -23,6 +28,7 @@ function readFixtureKey(name, enc) {
module.exports = {
fixturesDir,
path: fixturesPath,
+ fileURL: fixturesFileURL,
readSync: readFixtureSync,
readKey: readFixtureKey
};
Index: node-v12.22.12/test/fixtures/es-module-specifiers/index.mjs
===================================================================
--- node-v12.22.12.orig/test/fixtures/es-module-specifiers/index.mjs
+++ node-v12.22.12/test/fixtures/es-module-specifiers/index.mjs
@@ -1,10 +1,11 @@
import explicit from 'explicit-main';
import implicit from 'implicit-main';
import implicitModule from 'implicit-main-type-module';
+import noMain from 'no-main-field';
function getImplicitCommonjs () {
return import('implicit-main-type-commonjs');
}
-export {explicit, implicit, implicitModule, getImplicitCommonjs};
+export {explicit, implicit, implicitModule, getImplicitCommonjs, noMain};
export default 'success';
Index: node-v12.22.12/test/fixtures/es-module-specifiers/node_modules/no-main-field/index.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/es-module-specifiers/node_modules/no-main-field/index.js
@@ -0,0 +1,3 @@
+'use strict';
+module.exports = 'no main field';
+
Index: node-v12.22.12/test/fixtures/es-module-specifiers/node_modules/no-main-field/package.json
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/es-module-specifiers/node_modules/no-main-field/package.json
@@ -0,0 +1 @@
+{}
Index: node-v12.22.12/test/parallel/test-module-prototype-mutation.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/parallel/test-module-prototype-mutation.js
@@ -0,0 +1,13 @@
+'use strict';
+const common = require('../common');
+const fixtures = require('../common/fixtures');
+const assert = require('assert');
+
+assert.strictEqual(
+ require(fixtures.path('es-module-specifiers', 'node_modules', 'no-main-field')),
+ 'no main field'
+);
+
+import(fixtures.fileURL('es-module-specifiers', 'index.mjs'))
+ .then(common.mustCall((module) => assert.strictEqual(module.noMain, 'no main field')));
+
Index: node-v12.22.12/test/message/source_map_throw_catch.out
===================================================================
--- node-v12.22.12.orig/test/message/source_map_throw_catch.out
+++ node-v12.22.12/test/message/source_map_throw_catch.out
@@ -8,7 +8,7 @@ Error: an exception
at Object.Module._extensions..js (internal/modules/cjs/loader.js:*)
at Module.load (internal/modules/cjs/loader.js:*)
at Function.Module._load (internal/modules/cjs/loader.js:*)
- at Module.require (internal/modules/cjs/loader.js:*)
+ at Module.internalRequire (internal/modules/cjs/loader.js:*)
at require (internal/modules/cjs/helpers.js:*)
at Object.<anonymous> (*source_map_throw_catch.js:6:3)
at Module._compile (internal/modules/cjs/loader.js:*)
Index: node-v12.22.12/test/message/source_map_throw_first_tick.out
===================================================================
--- node-v12.22.12.orig/test/message/source_map_throw_first_tick.out
+++ node-v12.22.12/test/message/source_map_throw_first_tick.out
@@ -8,7 +8,7 @@ Error: an exception
at Object.Module._extensions..js (internal/modules/cjs/loader.js:*)
at Module.load (internal/modules/cjs/loader.js:*)
at Function.Module._load (internal/modules/cjs/loader.js:*)
- at Module.require (internal/modules/cjs/loader.js:*)
+ at Module.internalRequire (internal/modules/cjs/loader.js:*)
at require (internal/modules/cjs/helpers.js:*)
at Object.<anonymous> (*source_map_throw_first_tick.js:5:1)
at Module._compile (internal/modules/cjs/loader.js:*)
Index: node-v12.22.12/src/env.h
===================================================================
--- node-v12.22.12.orig/src/env.h
+++ node-v12.22.12/src/env.h
@@ -161,6 +161,7 @@ constexpr size_t kFsStatsBufferLength =
V(napi_wrapper, "node:napi:wrapper") \
V(sab_lifetimepartner_symbol, "node:sharedArrayBufferLifetimePartner") \
V(untransferable_object_private_symbol, "node:untransferableObject") \
+ V(require_private_symbol, "node:require_private_symbol")
// Symbols are per-isolate primitives but Environment proxies them
// for the sake of convenience.
Index: node-v12.22.12/test/fixtures/policy-manifest/object-define-property-bypass.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/object-define-property-bypass.js
@@ -0,0 +1,19 @@
+let requires = new WeakMap()
+Object.defineProperty(Object.getPrototypeOf(module), 'require', {
+ get() {
+ return requires.get(this);
+ },
+ set(v) {
+ requires.set(this, v);
+ process.nextTick(() => {
+ let fs = Reflect.apply(v, this, ['fs'])
+ if (typeof fs.readFileSync === 'function') {
+ process.exit(1);
+ }
+ })
+ return requires.get(this);
+ },
+ configurable: true
+})
+
+require('./valid-module')
Index: node-v12.22.12/test/fixtures/policy-manifest/onerror-exit.json
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/onerror-exit.json
@@ -0,0 +1,9 @@
+{
+ "onerror": "exit",
+ "scopes": {
+ "file:": {
+ "integrity": true,
+ "dependencies": {}
+ }
+ }
+}
Index: node-v12.22.12/test/fixtures/policy-manifest/onerror-resource-exit.json
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/onerror-resource-exit.json
@@ -0,0 +1,17 @@
+{
+ "onerror": "exit",
+ "resources": {
+ "./object-define-property-bypass.js": {
+ "integrity": true,
+ "dependencies": {
+ "./valid-module": true
+ }
+ },
+ "./valid-module.js": {
+ "integrity": true,
+ "dependencies": {
+ "fs": true
+ }
+ }
+ }
+}
Index: node-v12.22.12/test/parallel/test-policy-manifest.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/parallel/test-policy-manifest.js
@@ -0,0 +1,63 @@
+'use strict';
+
+const common = require('../common');
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+common.requireNoPackageJSONAbove();
+
+const assert = require('assert');
+const { spawnSync } = require('child_process');
+const fixtures = require('../common/fixtures.js');
+
+{
+ const policyFilepath = fixtures.path('policy-manifest', 'onerror-exit.json');
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ '-e',
+ 'require("os").cpus()',
+ ]);
+
+ assert.notStrictEqual(result.status, 0);
+ const stderr = result.stderr.toString();
+ assert.match(stderr, /ERR_MANIFEST_ASSERT_INTEGRITY/);
+ assert.match(stderr, /The resource was not found in the policy/);
+}
+
+{
+ const policyFilepath = fixtures.path('policy-manifest', 'onerror-exit.json');
+ const mainModuleBypass = fixtures.path(
+ 'policy-manifest',
+ 'main-module-bypass.js',
+ );
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ mainModuleBypass,
+ ]);
+
+ assert.notStrictEqual(result.status, 0);
+ const stderr = result.stderr.toString();
+ assert.match(stderr, /ERR_MANIFEST_ASSERT_INTEGRITY/);
+ assert.match(stderr, /The resource was not found in the policy/);
+}
+
+{
+ const policyFilepath = fixtures.path(
+ 'policy-manifest',
+ 'onerror-resource-exit.json',
+ );
+ const objectDefinePropertyBypass = fixtures.path(
+ 'policy-manifest',
+ 'object-define-property-bypass.js',
+ );
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ objectDefinePropertyBypass,
+ ]);
+
+ assert.strictEqual(result.status, 0);
+}
Index: node-v12.22.12/test/common/index.js
===================================================================
--- node-v12.22.12.orig/test/common/index.js
+++ node-v12.22.12/test/common/index.js
@@ -710,6 +710,20 @@ function gcUntil(name, condition) {
});
}
+function requireNoPackageJSONAbove(dir = __dirname) {
+ let possiblePackage = path.join(dir, '..', 'package.json');
+ let lastPackage = null;
+ while (possiblePackage !== lastPackage) {
+ if (fs.existsSync(possiblePackage)) {
+ assert.fail(
+ 'This test shouldn\'t load properties from a package.json above ' +
+ `its file location. Found package.json at ${possiblePackage}.`);
+ }
+ lastPackage = possiblePackage;
+ possiblePackage = path.join(possiblePackage, '..', '..', 'package.json');
+ }
+}
+
const common = {
allowGlobals,
buildType,
@@ -751,6 +765,7 @@ const common = {
platformTimeout,
printSkipMessage,
pwdCommand,
+ requireNoPackageJSONAbove,
runWithInvalidFD,
skip,
skipIf32Bits,
Index: node-v12.22.12/lib/internal/policy/manifest.js
===================================================================
--- node-v12.22.12.orig/lib/internal/policy/manifest.js
+++ node-v12.22.12/lib/internal/policy/manifest.js
@@ -115,7 +115,7 @@ class Manifest {
}
this.#reaction = reaction;
- const manifestEntries = ObjectEntries(obj.resources);
+ const manifestEntries = ObjectEntries(obj.resources ? obj.resources : ObjectCreate(null));
const parsedURLs = new SafeMap();
for (let i = 0; i < manifestEntries.length; i++) {
Index: node-v12.22.12/test/fixtures/policy-manifest/valid-module.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/valid-module.js
@@ -0,0 +1,2 @@
+
+
Index: node-v12.22.12/test/fixtures/policy-manifest/main-module-bypass.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/main-module-bypass.js
@@ -0,0 +1 @@
+process.mainModule.require('os').cpus();

28
CVE-2023-23920.patch Normal file
View File

@ -0,0 +1,28 @@
commit 97a0443f1369e65cf656a529b2f5433bfd56ad92
Author: RafaelGSS <rafael.nunu@hotmail.com>
Date: Wed Jan 18 17:37:37 2023 -0300
build: build ICU with ICU_NO_USER_DATA_OVERRIDE
CVE-ID: CVE-2023-23920
Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/377
PR-URL: https://github.com/nodejs-private/node-private/pull/374
Refs: https://hackerone.com/bugs?subject=nodejs&report_id=1625036
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
diff --git a/configure.py b/configure.py
index 892e1d4202..9a75dbb76d 100755
--- a/configure.py
+++ b/configure.py
@@ -1487,6 +1487,9 @@ def configure_intl(o):
# always set icu_small, node.gyp depends on it being defined.
o['variables']['icu_small'] = b(False)
+ # prevent data override
+ o['defines'] += ['ICU_NO_USER_DATA_OVERRIDE']
+
with_intl = options.with_intl
with_icu_source = options.with_icu_source
have_icu_path = bool(options.with_icu_path)

62
CVE-2023-30581.patch Normal file
View File

@ -0,0 +1,62 @@
commit a6f4e87bc913ff18c1859b8a350c24f744355e66
Author: RafaelGSS <rafael.nunu@hotmail.com>
Date: Mon May 29 16:40:15 2023 -0300
policy: handle mainModule.__proto__ bypass
Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/418
PR-URL: https://github.com/nodejs-private/node-private/pull/416
Fixes: https://hackerone.com/bugs?subject=nodejs&report_id=1877919
Reviewed-By: Rich Trott <rtrott@gmail.com>
CVE-ID: CVE-2023-30581
Index: node-v12.22.12/lib/internal/modules/cjs/loader.js
===================================================================
--- node-v12.22.12.orig/lib/internal/modules/cjs/loader.js
+++ node-v12.22.12/lib/internal/modules/cjs/loader.js
@@ -167,6 +167,7 @@ function Module(id = '', parent) {
if (manifest) {
const moduleURL = pathToFileURL(id);
redirects = manifest.getRedirector(moduleURL);
+ setOwnProperty(this.__proto__, 'require', makeRequireFunction(this, redirects));
}
setOwnProperty(this, 'require', makeRequireFunction(this, redirects));
// Loads a module at the given file path. Returns that module's
@@ -708,7 +709,7 @@ Module._load = function(request, parent,
const module = cachedModule || new Module(filename, parent);
if (isMain) {
- process.mainModule = module;
+ setOwnProperty(process, 'mainModule', module);
setOwnProperty(module.require, 'main', process.mainModule);
module.id = '.';
}
Index: node-v12.22.12/test/fixtures/policy-manifest/main-module-proto-bypass.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/main-module-proto-bypass.js
@@ -0,0 +1 @@
+process.mainModule.__proto__.require("os")
Index: node-v12.22.12/test/parallel/test-policy-manifest.js
===================================================================
--- node-v12.22.12.orig/test/parallel/test-policy-manifest.js
+++ node-v12.22.12/test/parallel/test-policy-manifest.js
@@ -61,3 +61,18 @@ const fixtures = require('../common/fixt
assert.strictEqual(result.status, 0);
}
+{
+ const policyFilepath = fixtures.path('policy-manifest', 'onerror-exit.json');
+ const mainModuleBypass = fixtures.path('policy-manifest', 'main-module-proto-bypass.js');
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ mainModuleBypass,
+ ]);
+
+ assert.notStrictEqual(result.status, 0);
+ const stderr = result.stderr.toString();
+ assert.match(stderr, /ERR_MANIFEST_ASSERT_INTEGRITY/);
+ assert.match(stderr, /The resource was not found in the policy/);
+}
+

2700
CVE-2023-30589.patch Normal file

File diff suppressed because it is too large Load Diff

165
CVE-2023-30590.patch Normal file
View File

@ -0,0 +1,165 @@
commit 1a5c9284ebce5cd71cf7a3c29759a748c373ac85
Author: Tobias Nießen <tobias.niessen@tuwien.ac.at>
Date: Mon Jun 12 19:44:48 2023 +0200
doc,test: clarify behavior of DH generateKeys
The DiffieHellman class is an old and thin wrapper around certain
OpenSSL functions, many of which are deprecated in OpenSSL 3.0. Because
the Node.js API mirrors the OpenSSL API, it adopts some of its
peculiarities, but the Node.js documentation does not properly reflect
these. Most importantly, despite the documentation saying otherwise,
diffieHellman.generateKeys() does not generate a new private key when
one has already been set or generated. Based on the documentation alone,
users may be led to misuse the API in a way that results in key reuse,
which can have drastic negative consequences for subsequent operations
that consume the shared secret.
These design issues in this old API have been around for many years, and
we are not currently aware of any misuse in the ecosystem that falls
into the above scenario. Changing the behavior of the API would be a
significant breaking change and is thus not appropriate for a security
release (nor is it a goal.) The reported issue is treated as CWE-1068
(after a vast amount of uncertainty whether to treat it as a
vulnerability at all), therefore, this change only updates the
documentation to match the actual behavior. Tests are also added that
demonstrate this particular oddity.
Newer APIs exist that can be used for some, but not all, Diffie-Hellman
operations (e.g., crypto.diffieHellman() that was added in 2020). We
should keep modernizing crypto APIs, but that is a non-goal for this
security release.
The ECDH class mirrors the DiffieHellman class in many ways, but it does
not appear to be affected by this particular peculiarity. In particular,
ecdh.generateKeys() does appear to always generate a new private key.
PR-URL: https://github.com/nodejs-private/node-private/pull/426
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
CVE-ID: CVE-2023-30590
Index: node-v12.22.12/doc/api/crypto.md
===================================================================
--- node-v12.22.12.orig/doc/api/crypto.md
+++ node-v12.22.12/doc/api/crypto.md
@@ -632,12 +632,17 @@ added: v0.5.0
* `encoding` {string} The [encoding][] of the return value.
* Returns: {Buffer | string}
-Generates private and public Diffie-Hellman key values, and returns
+Generates private and public Diffie-Hellman key values unless they have been
+generated or computed already, and returns
the public key in the specified `encoding`. This key should be
transferred to the other party.
If `encoding` is provided a string is returned; otherwise a
[`Buffer`][] is returned.
+This function is a thin wrapper around [`DH_generate_key()`][]. In particular,
+once a private key has been generated or set, calling this function only updates
+the public key but does not generate a new private key.
+
### `diffieHellman.getGenerator([encoding])`
<!-- YAML
added: v0.5.0
@@ -699,6 +704,10 @@ Sets the Diffie-Hellman private key. If
to be a string. If no `encoding` is provided, `privateKey` is expected
to be a [`Buffer`][], `TypedArray`, or `DataView`.
+This function does not automatically compute the associated public key. Either
+[`diffieHellman.setPublicKey()`][] or [`diffieHellman.generateKeys()`][] can be
+used to manually provide the public key or to automatically derive it.
+
### `diffieHellman.setPublicKey(publicKey[, encoding])`
<!-- YAML
added: v0.5.0
@@ -3527,6 +3536,7 @@ See the [list of SSL OP Flags][] for det
</table>
[`Buffer`]: buffer.html
+[`DH_generate_key()`]: https://www.openssl.org/docs/man3.0/man3/DH_generate_key.html
[`EVP_BytesToKey`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_BytesToKey.html
[`KeyObject`]: #crypto_class_keyobject
[`Sign`]: #crypto_class_sign
@@ -3559,6 +3569,7 @@ See the [list of SSL OP Flags][] for det
[`crypto.scrypt()`]: #crypto_crypto_scrypt_password_salt_keylen_options_callback
[`decipher.final()`]: #crypto_decipher_final_outputencoding
[`decipher.update()`]: #crypto_decipher_update_data_inputencoding_outputencoding
+[`diffieHellman.generateKeys()`]: #diffiehellmangeneratekeysencoding
[`diffieHellman.setPublicKey()`]: #crypto_diffiehellman_setpublickey_publickey_encoding
[`ecdh.generateKeys()`]: #crypto_ecdh_generatekeys_encoding_format
[`ecdh.setPrivateKey()`]: #crypto_ecdh_setprivatekey_privatekey_encoding
Index: node-v12.22.12/test/parallel/test-crypto-dh.js
===================================================================
--- node-v12.22.12.orig/test/parallel/test-crypto-dh.js
+++ node-v12.22.12/test/parallel/test-crypto-dh.js
@@ -8,7 +8,8 @@ const crypto = require('crypto');
// Test Diffie-Hellman with two parties sharing a secret,
// using various encodings as we go along
-const dh1 = crypto.createDiffieHellman(common.hasFipsCrypto ? 1024 : 256);
+const size = common.hasFipsCrypto ? 1024 : 256;
+const dh1 = crypto.createDiffieHellman(size);
const p1 = dh1.getPrime('buffer');
const dh2 = crypto.createDiffieHellman(p1, 'buffer');
let key1 = dh1.generateKeys();
@@ -471,3 +472,59 @@ assert.throws(
'crypto.getDiffieHellman(\'modp1\').setPublicKey(\'\') ' +
'failed to throw the expected error.'
);
+
+{
+ function unlessInvalidState(f) {
+ try {
+ return f();
+ } catch (err) {
+ // all errors thrown here are invalid state about missing keys
+// if (err.code !== 'ERR_CRYPTO_INVALID_STATE') {
+//console.log(err);
+// throw err;
+// }
+ }
+ }
+
+ function testGenerateKeysChangesKeys(setup, expected) {
+ const dh = crypto.createDiffieHellman(size);
+ setup(dh);
+ const firstPublicKey = unlessInvalidState(() => dh.getPublicKey());
+ const firstPrivateKey = unlessInvalidState(() => dh.getPrivateKey());
+ dh.generateKeys();
+ const secondPublicKey = dh.getPublicKey();
+ const secondPrivateKey = dh.getPrivateKey();
+ function changed(shouldChange, first, second) {
+ if (shouldChange) {
+ assert.notDeepStrictEqual(first, second);
+ } else {
+ assert.deepStrictEqual(first, second);
+ }
+ }
+ changed(expected.includes('public'), firstPublicKey, secondPublicKey);
+ changed(expected.includes('private'), firstPrivateKey, secondPrivateKey);
+ }
+
+ // Both the private and the public key are missing: generateKeys() generates both.
+ testGenerateKeysChangesKeys(() => {
+ // No setup.
+ }, ['public', 'private']);
+
+ // Neither key is missing: generateKeys() does nothing.
+ testGenerateKeysChangesKeys((dh) => {
+ dh.generateKeys();
+ }, []);
+
+ // Only the public key is missing: generateKeys() generates only the public key.
+ testGenerateKeysChangesKeys((dh) => {
+ dh.setPrivateKey(Buffer.from('01020304', 'hex'));
+ }, ['public']);
+
+ // The public key is outdated: generateKeys() generates only the public key.
+ testGenerateKeysChangesKeys((dh) => {
+ const oldPublicKey = dh.generateKeys();
+ dh.setPrivateKey(Buffer.from('01020304', 'hex'));
+ assert.deepStrictEqual(dh.getPublicKey(), oldPublicKey);
+ }, ['public']);
+}
+

View File

@ -0,0 +1,122 @@
commit d8ccfe9ad4dce9da900cff9dd2b934dfa3600b8b
Author: RafaelGSS <rafael.nunu@hotmail.com>
Date: Mon May 29 19:45:33 2023 -0300
policy: handle Module.constructor and main.extensions bypass
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs-private/node-private/pull/445
Refs: https://hackerone.com/bugs?subject=nodejs&report_id=1960870
Refs: https://hackerone.com/bugs?subject=nodejs&report_id=2043807
CVE-ID: CVE-2023-32002,CVE-2023-32006
Index: node-v12.22.12/test/fixtures/policy-manifest/createRequire-bypass.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/createRequire-bypass.js
@@ -0,0 +1,2 @@
+const os = module.constructor.createRequire('file:///os-access-module.js')('os')
+os.cpus()
\ No newline at end of file
Index: node-v12.22.12/test/fixtures/policy-manifest/main-constructor-bypass.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/main-constructor-bypass.js
@@ -0,0 +1,2 @@
+const m = new require.main.constructor();
+m.require('./invalid-module')
Index: node-v12.22.12/test/fixtures/policy-manifest/main-constructor-extensions-bypass.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/main-constructor-extensions-bypass.js
@@ -0,0 +1,2 @@
+const m = new require.main.constructor();
+require.extensions['.js'](m, './invalid-module')
Index: node-v12.22.12/test/fixtures/policy-manifest/manifest-impersonate.json
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/manifest-impersonate.json
@@ -0,0 +1,13 @@
+{
+ "resources": {
+ "./createRequire-bypass.js": {
+ "integrity": true
+ },
+ "/os-access-module.js": {
+ "integrity": true,
+ "dependencies": {
+ "os": true
+ }
+ }
+ }
+}
\ No newline at end of file
Index: node-v12.22.12/test/fixtures/policy-manifest/module-constructor-bypass.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy-manifest/module-constructor-bypass.js
@@ -0,0 +1 @@
+module.constructor._load('child_process');
Index: node-v12.22.12/test/parallel/test-policy-manifest.js
===================================================================
--- node-v12.22.12.orig/test/parallel/test-policy-manifest.js
+++ node-v12.22.12/test/parallel/test-policy-manifest.js
@@ -76,3 +76,58 @@ const fixtures = require('../common/fixt
assert.match(stderr, /The resource was not found in the policy/);
}
+
+{
+ const policyFilepath = fixtures.path('policy-manifest', 'onerror-exit.json');
+ const mainModuleBypass = fixtures.path('policy-manifest', 'module-constructor-bypass.js');
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ mainModuleBypass,
+ ]);
+ assert.notStrictEqual(result.status, 0);
+ const stderr = result.stderr.toString();
+ assert.match(stderr, /ERR_MANIFEST_ASSERT_INTEGRITY/);
+}
+
+{
+ const policyFilepath = fixtures.path('policy-manifest', 'manifest-impersonate.json');
+ const createRequireBypass = fixtures.path('policy-manifest', 'createRequire-bypass.js');
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ createRequireBypass,
+ ]);
+
+ assert.notStrictEqual(result.status, 0);
+ const stderr = result.stderr.toString();
+ assert.match(stderr, /policy is not defined/);
+}
+
+{
+ const policyFilepath = fixtures.path('policy-manifest', 'onerror-exit.json');
+ const mainModuleBypass = fixtures.path('policy-manifest', 'main-constructor-bypass.js');
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ mainModuleBypass,
+ ]);
+
+ assert.notStrictEqual(result.status, 0);
+ const stderr = result.stderr.toString();
+ assert.match(stderr, /ERR_MANIFEST_ASSERT_INTEGRITY/);
+}
+
+{
+ const policyFilepath = fixtures.path('policy-manifest', 'onerror-exit.json');
+ const mainModuleBypass = fixtures.path('policy-manifest', 'main-constructor-extensions-bypass.js');
+ const result = spawnSync(process.execPath, [
+ '--experimental-policy',
+ policyFilepath,
+ mainModuleBypass,
+ ]);
+
+ assert.notStrictEqual(result.status, 0);
+ const stderr = result.stderr.toString();
+ assert.match(stderr, /ERR_MANIFEST_ASSERT_INTEGRITY/);
+}

160
CVE-2023-32559.patch Normal file
View File

@ -0,0 +1,160 @@
commit 242aaa0caaf0c15109067b598d58fdeae603c5fd
Author: Tobias Nießen <tobias.niessen@tuwien.ac.at>
Date: Sun Apr 16 22:26:47 2023 +0200
policy: disable process.binding() when enabled
process.binding() can be used to trivially bypass restrictions imposed
through a policy. Since the function is deprecated already, simply
replace it with a stub when a policy is being enabled.
Fixes: https://hackerone.com/bugs?report_id=1946470
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
CVE-ID: CVE-2023-32559
PR-URL: https://github.com/nodejs-private/node-private/pull/459
Index: node-v12.22.12/doc/api/deprecations.md
===================================================================
--- node-v12.22.12.orig/doc/api/deprecations.md
+++ node-v12.22.12/doc/api/deprecations.md
@@ -2162,6 +2162,9 @@ Type: Documentation-only (supports [`--p
`process.binding()` is for use by Node.js internal code only.
+While `process.binding()` has not reached End-of-Life status in general, it is
+unavailable when [policies][] are enabled.
+
<a id="DEP0112"></a>
### DEP0112: `dgram` private APIs
<!-- YAML
@@ -2710,3 +2713,5 @@ const moduleParents = Object.values(requ
[from_arraybuffer]: buffer.html#buffer_static_method_buffer_from_arraybuffer_byteoffset_length
[from_string_encoding]: buffer.html#buffer_static_method_buffer_from_string_encoding
[legacy `urlObject`]: url.html#url_legacy_urlobject
+[policies]: permissions.md#policies
+
Index: node-v12.22.12/doc/api/errors.md
===================================================================
--- node-v12.22.12.orig/doc/api/errors.md
+++ node-v12.22.12/doc/api/errors.md
@@ -610,6 +610,14 @@ A human-readable string describing the r
<a id="nodejs-error-codes"></a>
## Node.js error codes
+<a id="ERR_ACCESS_DENIED"></a>
+
+### `ERR_ACCESS_DENIED`
+
+A special type of error that is triggered whenever Node.js tries to get access
+to a resource restricted by the [policy][] manifest.
+For example, `process.binding`.
+
<a id="ERR_AMBIGUOUS_ARGUMENT"></a>
### `ERR_AMBIGUOUS_ARGUMENT`
Index: node-v12.22.12/lib/internal/errors.js
===================================================================
--- node-v12.22.12.orig/lib/internal/errors.js
+++ node-v12.22.12/lib/internal/errors.js
@@ -746,6 +746,10 @@ module.exports = {
// Note: Please try to keep these in alphabetical order
//
// Note: Node.js specific errors must begin with the prefix ERR_
+
+E('ERR_ACCESS_DENIED',
+ 'Access to this API has been restricted. Permission: %s',
+ Error);
E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
E('ERR_ASSERTION', '%s', Error);
Index: node-v12.22.12/lib/internal/process/policy.js
===================================================================
--- node-v12.22.12.orig/lib/internal/process/policy.js
+++ node-v12.22.12/lib/internal/process/policy.js
@@ -7,6 +7,7 @@ const {
} = primordials;
const {
+ ERR_ACCESS_DENIED,
ERR_MANIFEST_TDZ,
} = require('internal/errors').codes;
const { Manifest } = require('internal/policy/manifest');
@@ -32,6 +33,15 @@ module.exports = ObjectFreeze({
return o;
});
manifest = new Manifest(json, url);
+
+ // process.binding() is deprecated (DEP0111) and trivially allows bypassing
+ // policies, so if policies are enabled, make this API unavailable.
+ process.binding = function binding(_module) {
+ throw new ERR_ACCESS_DENIED('process.binding');
+ };
+ process._linkedBinding = function _linkedBinding(_module) {
+ throw new ERR_ACCESS_DENIED('process._linkedBinding');
+ };
},
get manifest() {
Index: node-v12.22.12/test/fixtures/policy/process-binding/app.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy/process-binding/app.js
@@ -0,0 +1,10 @@
+'use strict';
+
+const assert = require('assert');
+
+assert.throws(() => { process.binding(); }, {
+ code: 'ERR_ACCESS_DENIED'
+});
+assert.throws(() => { process._linkedBinding(); }, {
+ code: 'ERR_ACCESS_DENIED'
+});
Index: node-v12.22.12/test/fixtures/policy/process-binding/policy.json
===================================================================
--- /dev/null
+++ node-v12.22.12/test/fixtures/policy/process-binding/policy.json
@@ -0,0 +1,10 @@
+{
+ "resources": {
+ "./app.js": {
+ "integrity": true,
+ "dependencies": {
+ "assert": true
+ }
+ }
+ }
+}
Index: node-v12.22.12/test/parallel/test-policy-process-binding.js
===================================================================
--- /dev/null
+++ node-v12.22.12/test/parallel/test-policy-process-binding.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const common = require('../common');
+common.requireNoPackageJSONAbove();
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const fixtures = require('../common/fixtures');
+
+const assert = require('assert');
+const { spawnSync } = require('child_process');
+
+const dep = fixtures.path('policy', 'process-binding', 'app.js');
+const depPolicy = fixtures.path(
+ 'policy',
+ 'process-binding',
+ 'policy.json');
+const { status } = spawnSync(
+ process.execPath,
+ [
+ '--experimental-policy', depPolicy, dep,
+ ],
+ {
+ stdio: 'inherit'
+ },
+);
+assert.strictEqual(status, 0);

View File

@ -1,5 +1,5 @@
%bcond_with bootstrap
%global baserelease 4
%global baserelease 5
%{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}}
%global nodejs_epoch 1
%global nodejs_major 12
@ -83,13 +83,22 @@ Patch0001: 0001-Disable-running-gyp-on-shared-deps.patch
Patch0002: 0002-Install-both-binaries-and-use-libdir.patch
Patch0003: 0004-Make-AARCH64-compile-on-64KB-physical-pages.patch
Patch00010: 0005-use-getauxval-in-node_main_cc.patch
Patch00011: CVE-2022-43548-pre-1.patch
Patch00012: CVE-2022-43548-pre-2.patch
Patch00013: CVE-2022-43548.patch
Patch00014: CVE-2023-0286.patch
Patch00015: CVE-2023-0215.patch
Patch00016: CVE-2022-4304.patch
Patch00017: CVE-2022-4450.patch
Patch00011: CVE-2022-32212.patch
Patch00012: CVE-2022-32213-CVE-2022-32214-CVE-2022-32215.patch
Patch00013: CVE-2022-35256.patch
Patch00014: CVE-2022-43548.patch
Patch00015: CVE-2023-0286.patch
Patch00016: CVE-2023-0215.patch
Patch00017: CVE-2022-4304.patch
Patch00018: CVE-2022-4450.patch
Patch00019: CVE-2023-23918.patch
Patch00020: CVE-2023-30581.patch
Patch00021: CVE-2023-30589.patch
Patch00022: CVE-2023-30590.patch
Patch00023: CVE-2022-25881.patch
Patch00024: CVE-2023-23920.patch
Patch00025: CVE-2023-32559.patch
Patch00026: CVE-2023-32002-CVE-2023-32006.patch
BuildRequires: python3-devel
BuildRequires: zlib-devel
@ -492,6 +501,12 @@ end
%{_pkgdocdir}/npm/docs
%changelog
* Tue Aug 29 2023 wangkai <13474090681@163.com> - 1:12.22.11-5
- Fix CVE-2022-32212,CVE-2022-32213,CVE-2022-32214,CVE-2022-32215,
- CVE-2022-25881,CVE-2023-23918,CVE-2023-23920,CVE-2023-30589,
- CVE-2023-30590,CVE-2023-30581,CVE-2023-32002,CVE-2023-32006,
- CVE-2023-32559,CVE-2022-35256
* Wed Feb 22 2023 yaoxin <yaoxin30@h-partners.com> - 1:12.22.11-4
- Fix CVE-2023-0286,CVE-2023-0215,CVE-2022-4304 and CVE-2022-4450