Skip to content

Commit

Permalink
tools: add ArrayPrototypeConcat to the list of primordials to avoid
Browse files Browse the repository at this point in the history
PR-URL: #44445
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
aduh95 authored and juanarbol committed Jan 24, 2023
1 parent 55e4140 commit 1e32520
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 29 deletions.
12 changes: 6 additions & 6 deletions lib/internal/bootstrap/node.js
Expand Up @@ -56,8 +56,8 @@ setupPrepareStackTrace();

const {
Array,
ArrayPrototypeConcat,
ArrayPrototypeFill,
ArrayPrototypePushApply,
FunctionPrototypeCall,
JSONParse,
ObjectDefineProperty,
Expand Down Expand Up @@ -195,11 +195,11 @@ const rawMethods = internalBinding('process_methods');

process.getActiveResourcesInfo = function() {
const timerCounts = internalTimers.getTimerCounts();
return ArrayPrototypeConcat(
rawMethods._getActiveRequestsInfo(),
rawMethods._getActiveHandlesInfo(),
ArrayPrototypeFill(new Array(timerCounts.timeoutCount), 'Timeout'),
ArrayPrototypeFill(new Array(timerCounts.immediateCount), 'Immediate'));
const info = rawMethods._getActiveRequestsInfo();
ArrayPrototypePushApply(info, rawMethods._getActiveHandlesInfo());
ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.timeoutCount), 'Timeout'));
ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.immediateCount), 'Immediate'));
return info;
};

// TODO(joyeecheung): remove these
Expand Down
7 changes: 3 additions & 4 deletions lib/internal/debugger/inspect.js
@@ -1,11 +1,11 @@
'use strict';

const {
ArrayPrototypeConcat,
ArrayPrototypeForEach,
ArrayPrototypeJoin,
ArrayPrototypeMap,
ArrayPrototypePop,
ArrayPrototypePushApply,
ArrayPrototypeShift,
ArrayPrototypeSlice,
FunctionPrototypeBind,
Expand Down Expand Up @@ -79,9 +79,8 @@ const debugRegex = /Debugger listening on ws:\/\/\[?(.+?)\]?:(\d+)\//;
async function runScript(script, scriptArgs, inspectHost, inspectPort,
childPrint) {
await portIsFree(inspectHost, inspectPort);
const args = ArrayPrototypeConcat(
[`--inspect-brk=${inspectPort}`, script],
scriptArgs);
const args = [`--inspect-brk=${inspectPort}`, script];
ArrayPrototypePushApply(args, scriptArgs);
const child = spawn(process.execPath, args);
child.stdout.setEncoding('utf8');
child.stderr.setEncoding('utf8');
Expand Down
1 change: 1 addition & 0 deletions lib/internal/main/print_help.js
Expand Up @@ -31,6 +31,7 @@ for (const key of ObjectKeys(types))
// Environment variables are parsed ad-hoc throughout the code base,
// so we gather the documentation here.
const { hasIntl, hasSmallICU, hasNodeOptions } = internalBinding('config');
// eslint-disable-next-line node-core/avoid-prototype-pollution
const envVars = new SafeMap(ArrayPrototypeConcat([
['FORCE_COLOR', { helpText: "when set to 'true', 1, 2, 3, or an empty " +
'string causes NO_COLOR and NODE_DISABLE_COLORS to be ignored.' }],
Expand Down
16 changes: 12 additions & 4 deletions lib/internal/modules/cjs/loader.js
Expand Up @@ -23,7 +23,6 @@

const {
ArrayIsArray,
ArrayPrototypeConcat,
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
ArrayPrototypeIndexOf,
Expand Down Expand Up @@ -655,7 +654,13 @@ Module._findPath = function(request, paths, isMain) {
Module._pathCache[cacheKey] = filename;
return filename;
}
reportModuleNotFoundToWatchMode(basePath, ArrayPrototypeConcat([''], exts));

if (exts === undefined) {
exts = [''];
} else {
ArrayPrototypeUnshift(exts, '');
}
reportModuleNotFoundToWatchMode(basePath, exts);
}

return false;
Expand Down Expand Up @@ -769,9 +774,12 @@ Module._resolveLookupPaths = function(request, parent) {
StringPrototypeCharAt(request, 1) !== '/' &&
(!isWindows || StringPrototypeCharAt(request, 1) !== '\\'))) {

let paths = modulePaths;
let paths;
if (parent?.paths?.length) {
paths = ArrayPrototypeConcat(parent.paths, paths);
paths = ArrayPrototypeSlice(modulePaths);
ArrayPrototypeUnshiftApply(paths, parent.paths);
} else {
paths = modulePaths;
}

debug('looking for %j in %j', request, paths);
Expand Down
12 changes: 6 additions & 6 deletions lib/internal/modules/esm/resolve.js
Expand Up @@ -2,8 +2,8 @@

const {
ArrayIsArray,
ArrayPrototypeConcat,
ArrayPrototypeJoin,
ArrayPrototypePush,
ArrayPrototypeShift,
JSONParse,
JSONStringify,
Expand Down Expand Up @@ -1052,11 +1052,11 @@ function throwIfUnsupportedURLScheme(parsed, experimentalNetworkImports) {
)
)
) {
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(parsed, ArrayPrototypeConcat(
'file',
'data',
experimentalNetworkImports ? ['https', 'http'] : [],
));
const schemes = ['file', 'data'];
if (experimentalNetworkImports) {
ArrayPrototypePush(schemes, 'https', 'http');
}
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(parsed, schemes);
}
}

Expand Down
6 changes: 4 additions & 2 deletions lib/internal/perf/observe.js
Expand Up @@ -9,7 +9,6 @@ const {
ArrayPrototypePushApply,
ArrayPrototypeSlice,
ArrayPrototypeSort,
ArrayPrototypeConcat,
Error,
MathMax,
MathMin,
Expand Down Expand Up @@ -470,7 +469,10 @@ function filterBufferMapByNameAndType(name, type) {
// Unrecognized type;
return [];
} else {
bufferList = ArrayPrototypeConcat(markEntryBuffer, measureEntryBuffer, resourceTimingBuffer);
bufferList = [];
ArrayPrototypePushApply(bufferList, markEntryBuffer);
ArrayPrototypePushApply(bufferList, measureEntryBuffer);
ArrayPrototypePushApply(bufferList, resourceTimingBuffer);
}
if (name !== undefined) {
bufferList = ArrayPrototypeFilter(bufferList, (buffer) => buffer.name === name);
Expand Down
9 changes: 4 additions & 5 deletions lib/internal/util/inspector.js
@@ -1,8 +1,8 @@
'use strict';

const {
ArrayPrototypeConcat,
ArrayPrototypeSome,
ArrayPrototypePushApply,
FunctionPrototypeBind,
ObjectDefineProperty,
ObjectKeys,
Expand Down Expand Up @@ -69,10 +69,9 @@ function installConsoleExtensions(commandLineApi) {
const { makeRequireFunction } = require('internal/modules/cjs/helpers');
const consoleAPIModule = new CJSModule('<inspector console>');
const cwd = tryGetCwd();
consoleAPIModule.paths = ArrayPrototypeConcat(
CJSModule._nodeModulePaths(cwd),
CJSModule.globalPaths
);
consoleAPIModule.paths = [];
ArrayPrototypePushApply(consoleAPIModule.paths, CJSModule._nodeModulePaths(cwd));
ArrayPrototypePushApply(consoleAPIModule.paths, CJSModule.globalPaths);
commandLineApi.require = makeRequireFunction(consoleAPIModule);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/repl.js
Expand Up @@ -43,7 +43,6 @@
'use strict';

const {
ArrayPrototypeConcat,
ArrayPrototypeFilter,
ArrayPrototypeFindIndex,
ArrayPrototypeForEach,
Expand All @@ -52,6 +51,7 @@ const {
ArrayPrototypeMap,
ArrayPrototypePop,
ArrayPrototypePush,
ArrayPrototypePushApply,
ArrayPrototypeReverse,
ArrayPrototypeShift,
ArrayPrototypeSlice,
Expand Down Expand Up @@ -1333,7 +1333,9 @@ function complete(line, callback) {
} else if (RegExpPrototypeExec(/^\.\.?\//, completeOn) !== null) {
paths = [process.cwd()];
} else {
paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths);
paths = [];
ArrayPrototypePushApply(paths, module.paths);
ArrayPrototypePushApply(paths, CJSModule.globalPaths);
}

ArrayPrototypeForEach(paths, (dir) => {
Expand Down
4 changes: 4 additions & 0 deletions test/parallel/test-eslint-avoid-prototype-pollution.js
Expand Up @@ -256,5 +256,9 @@ new RuleTester({
code: 'PromiseRace([])',
errors: [{ message: /\bSafePromiseRace\b/ }]
},
{
code: 'ArrayPrototypeConcat([])',
errors: [{ message: /\bisConcatSpreadable\b/ }]
},
]
});
8 changes: 8 additions & 0 deletions tools/eslint-rules/avoid-prototype-pollution.js
Expand Up @@ -200,6 +200,14 @@ module.exports = {
message: `Use Safe${node.callee.name} instead of ${node.callee.name}`,
});
},

[CallExpression('ArrayPrototypeConcat')](node) {
context.report({
node,
message: '%Array.prototype.concat% looks up `@@isConcatSpreadable` ' +
'which can be subject to prototype pollution',
});
},
};
},
};

0 comments on commit 1e32520

Please sign in to comment.