mirror of
https://github.com/nodejs/node.git
synced 2025-04-29 06:19:07 +00:00

Greatly simplify how ESLint and its plugins are installed. PR-URL: https://github.com/nodejs/node/pull/53413 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
335 lines
13 KiB
JavaScript
335 lines
13 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
if ((!common.hasCrypto) || (!common.hasIntl)) {
|
|
common.skip('ESLint tests require crypto and Intl');
|
|
}
|
|
|
|
common.skipIfEslintMissing();
|
|
|
|
const RuleTester = require('../../tools/eslint/node_modules/eslint').RuleTester;
|
|
const rule = require('../../tools/eslint-rules/avoid-prototype-pollution');
|
|
|
|
new RuleTester()
|
|
.run('property-descriptor-no-prototype-pollution', rule, {
|
|
valid: [
|
|
'ObjectDefineProperties({}, {})',
|
|
'ObjectCreate(null, {})',
|
|
'ObjectDefineProperties({}, { key })',
|
|
'ObjectCreate(null, { key })',
|
|
'ObjectDefineProperties({}, { ...spread })',
|
|
'ObjectCreate(null, { ...spread })',
|
|
'ObjectDefineProperties({}, { key: valueDescriptor })',
|
|
'ObjectCreate(null, { key: valueDescriptor })',
|
|
'ObjectDefineProperties({}, { key: { ...{}, __proto__: null } })',
|
|
'ObjectCreate(null, { key: { ...{}, __proto__: null } })',
|
|
'ObjectDefineProperties({}, { key: { __proto__: null } })',
|
|
'ObjectCreate(null, { key: { __proto__: null } })',
|
|
'ObjectDefineProperties({}, { key: { __proto__: null, enumerable: true } })',
|
|
'ObjectCreate(null, { key: { __proto__: null, enumerable: true } })',
|
|
'ObjectDefineProperties({}, { key: { "__proto__": null } })',
|
|
'ObjectCreate(null, { key: { "__proto__": null } })',
|
|
'ObjectDefineProperties({}, { key: { \'__proto__\': null } })',
|
|
'ObjectCreate(null, { key: { \'__proto__\': null } })',
|
|
'ObjectDefineProperty({}, "key", ObjectCreate(null))',
|
|
'ReflectDefineProperty({}, "key", ObjectCreate(null))',
|
|
'ObjectDefineProperty({}, "key", valueDescriptor)',
|
|
'ReflectDefineProperty({}, "key", valueDescriptor)',
|
|
'ObjectDefineProperty({}, "key", { __proto__: null })',
|
|
'ReflectDefineProperty({}, "key", { __proto__: null })',
|
|
'ObjectDefineProperty({}, "key", { __proto__: null, enumerable: true })',
|
|
'ReflectDefineProperty({}, "key", { __proto__: null, enumerable: true })',
|
|
'ObjectDefineProperty({}, "key", { "__proto__": null })',
|
|
'ReflectDefineProperty({}, "key", { "__proto__": null })',
|
|
'ObjectDefineProperty({}, "key", { \'__proto__\': null })',
|
|
'ReflectDefineProperty({}, "key", { \'__proto__\': null })',
|
|
'async function myFn() { return { __proto__: null } }',
|
|
'async function myFn() { function myFn() { return {} } return { __proto__: null } }',
|
|
'const myFn = async function myFn() { return { __proto__: null } }',
|
|
'const myFn = async function () { return { __proto__: null } }',
|
|
'const myFn = async () => { return { __proto__: null } }',
|
|
'const myFn = async () => ({ __proto__: null })',
|
|
'function myFn() { return {} }',
|
|
'const myFn = function myFn() { return {} }',
|
|
'const myFn = function () { return {} }',
|
|
'const myFn = () => { return {} }',
|
|
'const myFn = () => ({})',
|
|
'StringPrototypeReplace("some string", "some string", "some replacement")',
|
|
'StringPrototypeReplaceAll("some string", "some string", "some replacement")',
|
|
'StringPrototypeSplit("some string", "some string")',
|
|
'new Proxy({}, otherObject)',
|
|
'new Proxy({}, someFactory())',
|
|
'new Proxy({}, { __proto__: null })',
|
|
'new Proxy({}, { __proto__: null, ...{} })',
|
|
'async function name(){return await SafePromiseAll([])}',
|
|
'async function name(){const val = await SafePromiseAll([])}',
|
|
],
|
|
invalid: [
|
|
{
|
|
code: 'ObjectDefineProperties({}, ObjectGetOwnPropertyDescriptors({}))',
|
|
errors: [{ message: /prototype pollution/ }],
|
|
},
|
|
{
|
|
code: 'ObjectCreate(null, ObjectGetOwnPropertyDescriptors({}))',
|
|
errors: [{ message: /prototype pollution/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperties({}, { key: {} })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectCreate(null, { key: {} })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperties({}, { key: { [void 0]: { ...{ __proto__: null } } } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectCreate(null, { key: { [void 0]: { ...{ __proto__: null } } } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperties({}, { key: { __proto__: Object.prototype } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectCreate(null, { key: { __proto__: Object.prototype } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperties({}, { key: { [`__proto__`]: null } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectCreate(null, { key: { [`__proto__`]: null } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperties({}, { key: { enumerable: true } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectCreate(null, { key: { enumerable: true } })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperty({}, "key", {})',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ReflectDefineProperty({}, "key", {})',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperty({}, "key", ObjectGetOwnPropertyDescriptor({}, "key"))',
|
|
errors: [{
|
|
message: /prototype pollution/,
|
|
suggestions: [{
|
|
desc: 'Wrap the property descriptor in a null-prototype object',
|
|
output: 'ObjectDefineProperty({}, "key", { __proto__: null,...ObjectGetOwnPropertyDescriptor({}, "key") })',
|
|
}],
|
|
}],
|
|
},
|
|
{
|
|
code: 'ReflectDefineProperty({}, "key", ObjectGetOwnPropertyDescriptor({}, "key"))',
|
|
errors: [{
|
|
message: /prototype pollution/,
|
|
suggestions: [{
|
|
desc: 'Wrap the property descriptor in a null-prototype object',
|
|
output:
|
|
'ReflectDefineProperty({}, "key", { __proto__: null,...ObjectGetOwnPropertyDescriptor({}, "key") })',
|
|
}],
|
|
}],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperty({}, "key", ReflectGetOwnPropertyDescriptor({}, "key"))',
|
|
errors: [{
|
|
message: /prototype pollution/,
|
|
suggestions: [{
|
|
desc: 'Wrap the property descriptor in a null-prototype object',
|
|
output:
|
|
'ObjectDefineProperty({}, "key", { __proto__: null,...ReflectGetOwnPropertyDescriptor({}, "key") })',
|
|
}],
|
|
}],
|
|
},
|
|
{
|
|
code: 'ReflectDefineProperty({}, "key", ReflectGetOwnPropertyDescriptor({}, "key"))',
|
|
errors: [{
|
|
message: /prototype pollution/,
|
|
suggestions: [{
|
|
desc: 'Wrap the property descriptor in a null-prototype object',
|
|
output:
|
|
'ReflectDefineProperty({}, "key", { __proto__: null,...ReflectGetOwnPropertyDescriptor({}, "key") })',
|
|
}],
|
|
}],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperty({}, "key", { __proto__: Object.prototype })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ReflectDefineProperty({}, "key", { __proto__: Object.prototype })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperty({}, "key", { [`__proto__`]: null })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ReflectDefineProperty({}, "key", { [`__proto__`]: null })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ObjectDefineProperty({}, "key", { enumerable: true })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'ReflectDefineProperty({}, "key", { enumerable: true })',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'async function myFn(){ return {} }',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'async function myFn(){ async function someOtherFn() { return { __proto__: null } } return {} }',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'async function myFn(){ if (true) { return {} } return { __proto__: null } }',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'const myFn = async function myFn(){ return {} }',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'const myFn = async function (){ return {} }',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'const myFn = async () => { return {} }',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'const myFn = async () => ({})',
|
|
errors: [{ message: /null-prototype/ }],
|
|
},
|
|
{
|
|
code: 'RegExpPrototypeTest(/some regex/, "some string")',
|
|
errors: [{
|
|
message: /looks up the "exec" property/,
|
|
suggestions: [{
|
|
desc: 'Use RegexpPrototypeExec instead',
|
|
output: 'RegExpPrototypeExec(/some regex/, "some string") !== null',
|
|
}],
|
|
}],
|
|
},
|
|
{
|
|
code: 'RegExpPrototypeSymbolMatch(/some regex/, "some string")',
|
|
errors: [{ message: /looks up the "exec" property/ }],
|
|
},
|
|
{
|
|
code: 'RegExpPrototypeSymbolMatchAll(/some regex/, "some string")',
|
|
errors: [{ message: /looks up the "exec" property/ }],
|
|
},
|
|
{
|
|
code: 'RegExpPrototypeSymbolSearch(/some regex/, "some string")',
|
|
errors: [{ message: /SafeStringPrototypeSearch/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeMatch("some string", /some regex/)',
|
|
errors: [{ message: /looks up the Symbol\.match property/ }],
|
|
},
|
|
{
|
|
code: 'let v = StringPrototypeMatch("some string", /some regex/)',
|
|
errors: [{ message: /looks up the Symbol\.match property/ }],
|
|
},
|
|
{
|
|
code: 'let v = StringPrototypeMatch("some string", new RegExp("some regex"))',
|
|
errors: [{ message: /looks up the Symbol\.match property/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeMatchAll("some string", /some regex/)',
|
|
errors: [{ message: /looks up the Symbol\.matchAll property/ }],
|
|
},
|
|
{
|
|
code: 'let v = StringPrototypeMatchAll("some string", new RegExp("some regex"))',
|
|
errors: [{ message: /looks up the Symbol\.matchAll property/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeReplace("some string", /some regex/, "some replacement")',
|
|
errors: [{ message: /looks up the Symbol\.replace property/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeReplace("some string", new RegExp("some regex"), "some replacement")',
|
|
errors: [{ message: /looks up the Symbol\.replace property/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeReplaceAll("some string", /some regex/, "some replacement")',
|
|
errors: [{ message: /looks up the Symbol\.replace property/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeReplaceAll("some string", new RegExp("some regex"), "some replacement")',
|
|
errors: [{ message: /looks up the Symbol\.replace property/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeSearch("some string", /some regex/)',
|
|
errors: [{ message: /SafeStringPrototypeSearch/ }],
|
|
},
|
|
{
|
|
code: 'StringPrototypeSplit("some string", /some regex/)',
|
|
errors: [{ message: /looks up the Symbol\.split property/ }],
|
|
},
|
|
{
|
|
code: 'new Proxy({}, {})',
|
|
errors: [{ message: /null-prototype/ }]
|
|
},
|
|
{
|
|
code: 'new Proxy({}, { [`__proto__`]: null })',
|
|
errors: [{ message: /null-prototype/ }]
|
|
},
|
|
{
|
|
code: 'new Proxy({}, { __proto__: Object.prototype })',
|
|
errors: [{ message: /null-prototype/ }]
|
|
},
|
|
{
|
|
code: 'new Proxy({}, { ...{ __proto__: null } })',
|
|
errors: [{ message: /null-prototype/ }]
|
|
},
|
|
{
|
|
code: 'PromisePrototypeCatch(promise, ()=>{})',
|
|
errors: [{ message: /\bPromisePrototypeThen\b/ }]
|
|
},
|
|
{
|
|
code: 'PromiseAll([])',
|
|
errors: [{ message: /\bSafePromiseAll\b/ }]
|
|
},
|
|
{
|
|
code: 'async function fn(){await SafePromiseAll([])}',
|
|
errors: [{ message: /\bSafePromiseAllReturnVoid\b/ }]
|
|
},
|
|
{
|
|
code: 'async function fn(){await SafePromiseAllSettled([])}',
|
|
errors: [{ message: /\bSafePromiseAllSettledReturnVoid\b/ }]
|
|
},
|
|
{
|
|
code: 'PromiseAllSettled([])',
|
|
errors: [{ message: /\bSafePromiseAllSettled\b/ }]
|
|
},
|
|
{
|
|
code: 'PromiseAny([])',
|
|
errors: [{ message: /\bSafePromiseAny\b/ }]
|
|
},
|
|
{
|
|
code: 'PromiseRace([])',
|
|
errors: [{ message: /\bSafePromiseRace\b/ }]
|
|
},
|
|
{
|
|
code: 'ArrayPrototypeConcat([])',
|
|
errors: [{ message: /\bisConcatSpreadable\b/ }]
|
|
},
|
|
]
|
|
});
|