lib: makeRequireFunction patch when experimental policy

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>

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: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
RafaelGSS 2023-02-13 15:41:30 -03:00
parent af91400886
commit 9b7db62276
2 changed files with 26 additions and 7 deletions

View File

@ -229,10 +229,9 @@ function Module(id = '', parent) {
if (manifest) { if (manifest) {
const moduleURL = pathToFileURL(id); const moduleURL = pathToFileURL(id);
redirects = manifest.getDependencyMapper(moduleURL); redirects = manifest.getDependencyMapper(moduleURL);
// TODO(rafaelgss): remove the necessity of this branch
setOwnProperty(this, 'require', makeRequireFunction(this, redirects));
} }
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; this[require_private_symbol] = internalRequire;
} }
@ -1143,6 +1142,23 @@ Module.prototype.load = function(filename) {
cascadedLoader.cjsCache.set(this, exports); cascadedLoader.cjsCache.set(this, exports);
}; };
// Loads a module at the given file path. Returns that module's
// `exports` property.
// Note: when using the experimental policy mechanism this function is overridden
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 // Resolved path to process.argv[1] will be lazily placed here
// (needed for setting breakpoint when called with --inspect-brk) // (needed for setting breakpoint when called with --inspect-brk)
let resolvedArgv; let resolvedArgv;
@ -1211,10 +1227,11 @@ function wrapSafe(filename, content, cjsModuleInstance) {
// Returns exception, if any. // Returns exception, if any.
Module.prototype._compile = function(content, filename) { Module.prototype._compile = function(content, filename) {
let moduleURL; let moduleURL;
let redirects;
const manifest = policy()?.manifest; const manifest = policy()?.manifest;
if (manifest) { if (manifest) {
moduleURL = pathToFileURL(filename); moduleURL = pathToFileURL(filename);
manifest.getDependencyMapper(moduleURL); redirects = manifest.getDependencyMapper(moduleURL);
manifest.assertIntegrity(moduleURL, content); manifest.assertIntegrity(moduleURL, content);
} }
@ -1244,6 +1261,7 @@ Module.prototype._compile = function(content, filename) {
} }
} }
const dirname = path.dirname(filename); const dirname = path.dirname(filename);
const require = makeRequireFunction(this, redirects);
let result; let result;
const exports = this.exports; const exports = this.exports;
const thisValue = exports; const thisValue = exports;
@ -1251,10 +1269,10 @@ Module.prototype._compile = function(content, filename) {
if (requireDepth === 0) statCache = new SafeMap(); if (requireDepth === 0) statCache = new SafeMap();
if (inspectorWrapper) { if (inspectorWrapper) {
result = inspectorWrapper(compiledWrapper, thisValue, exports, result = inspectorWrapper(compiledWrapper, thisValue, exports,
module.require, module, filename, dirname); require, module, filename, dirname);
} else { } else {
result = ReflectApply(compiledWrapper, thisValue, result = ReflectApply(compiledWrapper, thisValue,
[exports, module.require, module, filename, dirname]); [exports, require, module, filename, dirname]);
} }
hasLoadedAnyUserCJSModule = true; hasLoadedAnyUserCJSModule = true;
if (requireDepth === 0) statCache = null; if (requireDepth === 0) statCache = null;

View File

@ -115,7 +115,8 @@ function makeRequireFunction(mod, redirects) {
}; };
} else { } else {
require = function require(path) { require = function require(path) {
return mod[require_private_symbol](mod, path); // When no policy manifest, the original prototype.require is sustained
return mod.require(path);
}; };
} }