1'use strict'; 2 3const common = require('../common'); 4if ((!common.hasCrypto) || (!common.hasIntl)) { 5 common.skip('ESLint tests require crypto and Intl'); 6} 7 8common.skipIfEslintMissing(); 9 10const RuleTester = require('../../tools/node_modules/eslint').RuleTester; 11const rule = require('../../tools/eslint-rules/avoid-prototype-pollution'); 12 13new RuleTester({ 14 parserOptions: { ecmaVersion: 2022 }, 15}) 16 .run('property-descriptor-no-prototype-pollution', rule, { 17 valid: [ 18 'ObjectDefineProperties({}, {})', 19 'ObjectCreate(null, {})', 20 'ObjectDefineProperties({}, { key })', 21 'ObjectCreate(null, { key })', 22 'ObjectDefineProperties({}, { ...spread })', 23 'ObjectCreate(null, { ...spread })', 24 'ObjectDefineProperties({}, { key: valueDescriptor })', 25 'ObjectCreate(null, { key: valueDescriptor })', 26 'ObjectDefineProperties({}, { key: { ...{}, __proto__: null } })', 27 'ObjectCreate(null, { key: { ...{}, __proto__: null } })', 28 'ObjectDefineProperties({}, { key: { __proto__: null } })', 29 'ObjectCreate(null, { key: { __proto__: null } })', 30 'ObjectDefineProperties({}, { key: { __proto__: null, enumerable: true } })', 31 'ObjectCreate(null, { key: { __proto__: null, enumerable: true } })', 32 'ObjectDefineProperties({}, { key: { "__proto__": null } })', 33 'ObjectCreate(null, { key: { "__proto__": null } })', 34 'ObjectDefineProperties({}, { key: { \'__proto__\': null } })', 35 'ObjectCreate(null, { key: { \'__proto__\': null } })', 36 'ObjectDefineProperty({}, "key", ObjectCreate(null))', 37 'ReflectDefineProperty({}, "key", ObjectCreate(null))', 38 'ObjectDefineProperty({}, "key", valueDescriptor)', 39 'ReflectDefineProperty({}, "key", valueDescriptor)', 40 'ObjectDefineProperty({}, "key", { __proto__: null })', 41 'ReflectDefineProperty({}, "key", { __proto__: null })', 42 'ObjectDefineProperty({}, "key", { __proto__: null, enumerable: true })', 43 'ReflectDefineProperty({}, "key", { __proto__: null, enumerable: true })', 44 'ObjectDefineProperty({}, "key", { "__proto__": null })', 45 'ReflectDefineProperty({}, "key", { "__proto__": null })', 46 'ObjectDefineProperty({}, "key", { \'__proto__\': null })', 47 'ReflectDefineProperty({}, "key", { \'__proto__\': null })', 48 'StringPrototypeReplace("some string", "some string", "some replacement")', 49 'StringPrototypeReplaceAll("some string", "some string", "some replacement")', 50 'StringPrototypeSplit("some string", "some string")', 51 'new Proxy({}, otherObject)', 52 'new Proxy({}, someFactory())', 53 'new Proxy({}, { __proto__: null })', 54 'new Proxy({}, { __proto__: null, ...{} })', 55 'async function name(){return await SafePromiseAll([])}', 56 'async function name(){const val = await SafePromiseAll([])}', 57 ], 58 invalid: [ 59 { 60 code: 'ObjectDefineProperties({}, ObjectGetOwnPropertyDescriptors({}))', 61 errors: [{ message: /prototype pollution/ }], 62 }, 63 { 64 code: 'ObjectCreate(null, ObjectGetOwnPropertyDescriptors({}))', 65 errors: [{ message: /prototype pollution/ }], 66 }, 67 { 68 code: 'ObjectDefineProperties({}, { key: {} })', 69 errors: [{ message: /null-prototype/ }], 70 }, 71 { 72 code: 'ObjectCreate(null, { key: {} })', 73 errors: [{ message: /null-prototype/ }], 74 }, 75 { 76 code: 'ObjectDefineProperties({}, { key: { [void 0]: { ...{ __proto__: null } } } })', 77 errors: [{ message: /null-prototype/ }], 78 }, 79 { 80 code: 'ObjectCreate(null, { key: { [void 0]: { ...{ __proto__: null } } } })', 81 errors: [{ message: /null-prototype/ }], 82 }, 83 { 84 code: 'ObjectDefineProperties({}, { key: { __proto__: Object.prototype } })', 85 errors: [{ message: /null-prototype/ }], 86 }, 87 { 88 code: 'ObjectCreate(null, { key: { __proto__: Object.prototype } })', 89 errors: [{ message: /null-prototype/ }], 90 }, 91 { 92 code: 'ObjectDefineProperties({}, { key: { [`__proto__`]: null } })', 93 errors: [{ message: /null-prototype/ }], 94 }, 95 { 96 code: 'ObjectCreate(null, { key: { [`__proto__`]: null } })', 97 errors: [{ message: /null-prototype/ }], 98 }, 99 { 100 code: 'ObjectDefineProperties({}, { key: { enumerable: true } })', 101 errors: [{ message: /null-prototype/ }], 102 }, 103 { 104 code: 'ObjectCreate(null, { key: { enumerable: true } })', 105 errors: [{ message: /null-prototype/ }], 106 }, 107 { 108 code: 'ObjectDefineProperty({}, "key", {})', 109 errors: [{ message: /null-prototype/ }], 110 }, 111 { 112 code: 'ReflectDefineProperty({}, "key", {})', 113 errors: [{ message: /null-prototype/ }], 114 }, 115 { 116 code: 'ObjectDefineProperty({}, "key", ObjectGetOwnPropertyDescriptor({}, "key"))', 117 errors: [{ message: /prototype pollution/ }], 118 }, 119 { 120 code: 'ReflectDefineProperty({}, "key", ObjectGetOwnPropertyDescriptor({}, "key"))', 121 errors: [{ message: /prototype pollution/ }], 122 }, 123 { 124 code: 'ObjectDefineProperty({}, "key", ReflectGetOwnPropertyDescriptor({}, "key"))', 125 errors: [{ message: /prototype pollution/ }], 126 }, 127 { 128 code: 'ReflectDefineProperty({}, "key", ReflectGetOwnPropertyDescriptor({}, "key"))', 129 errors: [{ message: /prototype pollution/ }], 130 }, 131 { 132 code: 'ObjectDefineProperty({}, "key", { __proto__: Object.prototype })', 133 errors: [{ message: /null-prototype/ }], 134 }, 135 { 136 code: 'ReflectDefineProperty({}, "key", { __proto__: Object.prototype })', 137 errors: [{ message: /null-prototype/ }], 138 }, 139 { 140 code: 'ObjectDefineProperty({}, "key", { [`__proto__`]: null })', 141 errors: [{ message: /null-prototype/ }], 142 }, 143 { 144 code: 'ReflectDefineProperty({}, "key", { [`__proto__`]: null })', 145 errors: [{ message: /null-prototype/ }], 146 }, 147 { 148 code: 'ObjectDefineProperty({}, "key", { enumerable: true })', 149 errors: [{ message: /null-prototype/ }], 150 }, 151 { 152 code: 'ReflectDefineProperty({}, "key", { enumerable: true })', 153 errors: [{ message: /null-prototype/ }], 154 }, 155 { 156 code: 'RegExpPrototypeTest(/some regex/, "some string")', 157 errors: [{ message: /looks up the "exec" property/ }], 158 }, 159 { 160 code: 'RegExpPrototypeSymbolMatch(/some regex/, "some string")', 161 errors: [{ message: /looks up the "exec" property/ }], 162 }, 163 { 164 code: 'RegExpPrototypeSymbolMatchAll(/some regex/, "some string")', 165 errors: [{ message: /looks up the "exec" property/ }], 166 }, 167 { 168 code: 'RegExpPrototypeSymbolSearch(/some regex/, "some string")', 169 errors: [{ message: /SafeStringPrototypeSearch/ }], 170 }, 171 { 172 code: 'StringPrototypeMatch("some string", /some regex/)', 173 errors: [{ message: /looks up the Symbol\.match property/ }], 174 }, 175 { 176 code: 'let v = StringPrototypeMatch("some string", /some regex/)', 177 errors: [{ message: /looks up the Symbol\.match property/ }], 178 }, 179 { 180 code: 'let v = StringPrototypeMatch("some string", new RegExp("some regex"))', 181 errors: [{ message: /looks up the Symbol\.match property/ }], 182 }, 183 { 184 code: 'StringPrototypeMatchAll("some string", /some regex/)', 185 errors: [{ message: /looks up the Symbol\.matchAll property/ }], 186 }, 187 { 188 code: 'let v = StringPrototypeMatchAll("some string", new RegExp("some regex"))', 189 errors: [{ message: /looks up the Symbol\.matchAll property/ }], 190 }, 191 { 192 code: 'StringPrototypeReplace("some string", /some regex/, "some replacement")', 193 errors: [{ message: /looks up the Symbol\.replace property/ }], 194 }, 195 { 196 code: 'StringPrototypeReplace("some string", new RegExp("some regex"), "some replacement")', 197 errors: [{ message: /looks up the Symbol\.replace property/ }], 198 }, 199 { 200 code: 'StringPrototypeReplaceAll("some string", /some regex/, "some replacement")', 201 errors: [{ message: /looks up the Symbol\.replace property/ }], 202 }, 203 { 204 code: 'StringPrototypeReplaceAll("some string", new RegExp("some regex"), "some replacement")', 205 errors: [{ message: /looks up the Symbol\.replace property/ }], 206 }, 207 { 208 code: 'StringPrototypeSearch("some string", /some regex/)', 209 errors: [{ message: /SafeStringPrototypeSearch/ }], 210 }, 211 { 212 code: 'StringPrototypeSplit("some string", /some regex/)', 213 errors: [{ message: /looks up the Symbol\.split property/ }], 214 }, 215 { 216 code: 'new Proxy({}, {})', 217 errors: [{ message: /null-prototype/ }] 218 }, 219 { 220 code: 'new Proxy({}, { [`__proto__`]: null })', 221 errors: [{ message: /null-prototype/ }] 222 }, 223 { 224 code: 'new Proxy({}, { __proto__: Object.prototype })', 225 errors: [{ message: /null-prototype/ }] 226 }, 227 { 228 code: 'new Proxy({}, { ...{ __proto__: null } })', 229 errors: [{ message: /null-prototype/ }] 230 }, 231 { 232 code: 'PromisePrototypeCatch(promise, ()=>{})', 233 errors: [{ message: /\bPromisePrototypeThen\b/ }] 234 }, 235 { 236 code: 'PromiseAll([])', 237 errors: [{ message: /\bSafePromiseAll\b/ }] 238 }, 239 { 240 code: 'async function fn(){await SafePromiseAll([])}', 241 errors: [{ message: /\bSafePromiseAllReturnVoid\b/ }] 242 }, 243 { 244 code: 'async function fn(){await SafePromiseAllSettled([])}', 245 errors: [{ message: /\bSafePromiseAllSettledReturnVoid\b/ }] 246 }, 247 { 248 code: 'PromiseAllSettled([])', 249 errors: [{ message: /\bSafePromiseAllSettled\b/ }] 250 }, 251 { 252 code: 'PromiseAny([])', 253 errors: [{ message: /\bSafePromiseAny\b/ }] 254 }, 255 { 256 code: 'PromiseRace([])', 257 errors: [{ message: /\bSafePromiseRace\b/ }] 258 }, 259 { 260 code: 'ArrayPrototypeConcat([])', 261 errors: [{ message: /\bisConcatSpreadable\b/ }] 262 }, 263 ] 264 }); 265