Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tools: add ArrayPrototypeConcat to the list of primordials to avoid #44445

Merged
merged 2 commits into from Dec 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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,
Number,
Expand Down Expand Up @@ -174,11 +174,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 @@ -85,9 +85,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,
JSONStringify,
ObjectFreeze,
Expand Down Expand Up @@ -986,11 +986,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 @@ -513,7 +512,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 @@ -1332,7 +1332,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 @@ -295,5 +295,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 @@ -224,6 +224,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',
});
},
};
},
};