| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 93a34fa commit c7b7f2b
10 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -188,7 +188,7 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | |||
| 188 | 188 | privateUsages, | |
| 189 | 189 | extractable); | |
| 190 | 190 | ||
| 191 | - return { privateKey, publicKey }; | ||
| 191 | + return { __proto__: null, privateKey, publicKey }; | ||
| 192 | 192 | } | |
| 193 | 193 | ||
| 194 | 194 | function cfrgExportKey(key, format) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -146,7 +146,7 @@ async function ecGenerateKey(algorithm, extractable, keyUsages) { | |||
| 146 | 146 | privateUsages, | |
| 147 | 147 | extractable); | |
| 148 | 148 | ||
| 149 | - return { publicKey, privateKey }; | ||
| 149 | + return { __proto__: null, publicKey, privateKey }; | ||
| 150 | 150 | } | |
| 151 | 151 | ||
| 152 | 152 | function ecExportKey(key, format) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -219,7 +219,7 @@ async function rsaKeyGenerate( | |||
| 219 | 219 | privateUsages, | |
| 220 | 220 | extractable); | |
| 221 | 221 | ||
| 222 | - return { publicKey, privateKey }; | ||
| 222 | + return { __proto__: null, publicKey, privateKey }; | ||
| 223 | 223 | } | |
| 224 | 224 | ||
| 225 | 225 | function rsaExportKey(key, format) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -115,7 +115,7 @@ async function checkPaths(src, dest, opts) { | |||
| 115 | 115 | code: 'EINVAL', | |
| 116 | 116 | }); | |
| 117 | 117 | } | |
| 118 | - return { srcStat, destStat, skipped: false }; | ||
| 118 | + return { __proto__: null, srcStat, destStat, skipped: false }; | ||
| 119 | 119 | } | |
| 120 | 120 | ||
| 121 | 121 | function areIdentical(srcStat, destStat) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -580,7 +580,7 @@ async function read(handle, bufferOrParams, offset, length, position) { | |||
| 580 | 580 | length |= 0; | |
| 581 | 581 | ||
| 582 | 582 | if (length === 0) | |
| 583 | - return { bytesRead: length, buffer }; | ||
| 583 | + return { __proto__: null, bytesRead: length, buffer }; | ||
| 584 | 584 | ||
| 585 | 585 | if (buffer.byteLength === 0) { | |
| 586 | 586 | throw new ERR_INVALID_ARG_VALUE('buffer', buffer, | |
@@ -595,7 +595,7 @@ async function read(handle, bufferOrParams, offset, length, position) { | |||
| 595 | 595 | const bytesRead = (await binding.read(handle.fd, buffer, offset, length, | |
| 596 | 596 | position, kUsePromises)) || 0; | |
| 597 | 597 | ||
| 598 | - return { bytesRead, buffer }; | ||
| 598 | + return { __proto__: null, bytesRead, buffer }; | ||
| 599 | 599 | } | |
| 600 | 600 | ||
| 601 | 601 | async function readv(handle, buffers, position) { | |
@@ -606,12 +606,12 @@ async function readv(handle, buffers, position) { | |||
| 606 | 606 | ||
| 607 | 607 | const bytesRead = (await binding.readBuffers(handle.fd, buffers, position, | |
| 608 | 608 | kUsePromises)) || 0; | |
| 609 | - return { bytesRead, buffers }; | ||
| 609 | + return { __proto__: null, bytesRead, buffers }; | ||
| 610 | 610 | } | |
| 611 | 611 | ||
| 612 | 612 | async function write(handle, buffer, offsetOrOptions, length, position) { | |
| 613 | 613 | if (buffer?.byteLength === 0) | |
| 614 | - return { bytesWritten: 0, buffer }; | ||
| 614 | + return { __proto__: null, bytesWritten: 0, buffer }; | ||
| 615 | 615 | ||
| 616 | 616 | let offset = offsetOrOptions; | |
| 617 | 617 | if (isArrayBufferView(buffer)) { | |
@@ -636,14 +636,14 @@ async function write(handle, buffer, offsetOrOptions, length, position) { | |||
| 636 | 636 | const bytesWritten = | |
| 637 | 637 | (await binding.writeBuffer(handle.fd, buffer, offset, | |
| 638 | 638 | length, position, kUsePromises)) || 0; | |
| 639 | - return { bytesWritten, buffer }; | ||
| 639 | + return { __proto__: null, bytesWritten, buffer }; | ||
| 640 | 640 | } | |
| 641 | 641 | ||
| 642 | 642 | validateStringAfterArrayBufferView(buffer, 'buffer'); | |
| 643 | 643 | validateEncoding(buffer, length); | |
| 644 | 644 | const bytesWritten = (await binding.writeString(handle.fd, buffer, offset, | |
| 645 | 645 | length, kUsePromises)) || 0; | |
| 646 | - return { bytesWritten, buffer }; | ||
| 646 | + return { __proto__: null, bytesWritten, buffer }; | ||
| 647 | 647 | } | |
| 648 | 648 | ||
| 649 | 649 | async function writev(handle, buffers, position) { | |
@@ -653,12 +653,12 @@ async function writev(handle, buffers, position) { | |||
| 653 | 653 | position = null; | |
| 654 | 654 | ||
| 655 | 655 | if (buffers.length === 0) { | |
| 656 | - return { bytesWritten: 0, buffers }; | ||
| 656 | + return { __proto__: null, bytesWritten: 0, buffers }; | ||
| 657 | 657 | } | |
| 658 | 658 | ||
| 659 | 659 | const bytesWritten = (await binding.writeBuffers(handle.fd, buffers, position, | |
| 660 | 660 | kUsePromises)) || 0; | |
| 661 | - return { bytesWritten, buffers }; | ||
| 661 | + return { __proto__: null, bytesWritten, buffers }; | ||
| 662 | 662 | } | |
| 663 | 663 | ||
| 664 | 664 | async function rename(oldPath, newPath) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -378,6 +378,7 @@ class ESMLoader { | |||
| 378 | 378 | const { module } = await job.run(); | |
| 379 | 379 | ||
| 380 | 380 | return { | |
| 381 | + __proto__: null, | ||
| 381 | 382 | namespace: module.getNamespace(), | |
| 382 | 383 | }; | |
| 383 | 384 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -977,7 +977,7 @@ async function defaultResolve(specifier, context = {}) { | |||
| 977 | 977 | missing = false; | |
| 978 | 978 | } else if (destination) { | |
| 979 | 979 | const href = destination.href; | |
| 980 | - return { url: href }; | ||
| 980 | + return { __proto__: null, url: href }; | ||
| 981 | 981 | } | |
| 982 | 982 | if (missing) { | |
| 983 | 983 | // Prevent network requests from firing if resolution would be banned. | |
@@ -1035,7 +1035,7 @@ async function defaultResolve(specifier, context = {}) { | |||
| 1035 | 1035 | if (maybeReturn) return maybeReturn; | |
| 1036 | 1036 | ||
| 1037 | 1037 | // This must come after checkIfDisallowedImport | |
| 1038 | - if (parsed && parsed.protocol === 'node:') return { url: specifier }; | ||
| 1038 | + if (parsed && parsed.protocol === 'node:') return { __proto__: null, url: specifier }; | ||
| 1039 | 1039 | ||
| 1040 | 1040 | throwIfUnsupportedURLScheme(parsed, experimentalNetworkImports); | |
| 1041 | 1041 | ||
@@ -1087,6 +1087,7 @@ async function defaultResolve(specifier, context = {}) { | |||
| 1087 | 1087 | throwIfUnsupportedURLProtocol(url); | |
| 1088 | 1088 | ||
| 1089 | 1089 | return { | |
| 1090 | + __proto__: null, | ||
| 1090 | 1091 | // Do NOT cast `url` to a string: that will work even when there are real | |
| 1091 | 1092 | // problems, silencing them | |
| 1092 | 1093 | url: url.href, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -476,7 +476,7 @@ class ReadableStream { | |||
| 476 | 476 | ||
| 477 | 477 | async function returnSteps(value) { | |
| 478 | 478 | if (done) | |
| 479 | - return { done: true, value }; | ||
| 479 | + return { done: true, value }; // eslint-disable-line node-core/avoid-prototype-pollution | ||
| 480 | 480 | done = true; | |
| 481 | 481 | ||
| 482 | 482 | if (reader[kState].stream === undefined) { | |
@@ -488,11 +488,11 @@ class ReadableStream { | |||
| 488 | 488 | const result = readableStreamReaderGenericCancel(reader, value); | |
| 489 | 489 | readableStreamReaderGenericRelease(reader); | |
| 490 | 490 | await result; | |
| 491 | - return { done: true, value }; | ||
| 491 | + return { done: true, value }; // eslint-disable-line node-core/avoid-prototype-pollution | ||
| 492 | 492 | } | |
| 493 | 493 | ||
| 494 | 494 | readableStreamReaderGenericRelease(reader); | |
| 495 | - return { done: true, value }; | ||
| 495 | + return { done: true, value }; // eslint-disable-line node-core/avoid-prototype-pollution | ||
| 496 | 496 | } | |
| 497 | 497 | ||
| 498 | 498 | // TODO(@jasnell): Explore whether an async generator | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -45,6 +45,17 @@ new RuleTester({ | |||
| 45 | 45 | 'ReflectDefineProperty({}, "key", { "__proto__": null })', | |
| 46 | 46 | 'ObjectDefineProperty({}, "key", { \'__proto__\': null })', | |
| 47 | 47 | 'ReflectDefineProperty({}, "key", { \'__proto__\': null })', | |
| 48 | + 'async function myFn() { return { __proto__: null } }', | ||
| 49 | + 'async function myFn() { function myFn() { return {} } return { __proto__: null } }', | ||
| 50 | + 'const myFn = async function myFn() { return { __proto__: null } }', | ||
| 51 | + 'const myFn = async function () { return { __proto__: null } }', | ||
| 52 | + 'const myFn = async () => { return { __proto__: null } }', | ||
| 53 | + 'const myFn = async () => ({ __proto__: null })', | ||
| 54 | + 'function myFn() { return {} }', | ||
| 55 | + 'const myFn = function myFn() { return {} }', | ||
| 56 | + 'const myFn = function () { return {} }', | ||
| 57 | + 'const myFn = () => { return {} }', | ||
| 58 | + 'const myFn = () => ({})', | ||
| 48 | 59 | 'StringPrototypeReplace("some string", "some string", "some replacement")', | |
| 49 | 60 | 'StringPrototypeReplaceAll("some string", "some string", "some replacement")', | |
| 50 | 61 | 'StringPrototypeSplit("some string", "some string")', | |
@@ -150,6 +161,34 @@ new RuleTester({ | |||
| 150 | 161 | code: 'ReflectDefineProperty({}, "key", { enumerable: true })', | |
| 151 | 162 | errors: [{ message: /null-prototype/ }], | |
| 152 | 163 | }, | |
| 164 | + { | ||
| 165 | + code: 'async function myFn(){ return {} }', | ||
| 166 | + errors: [{ message: /null-prototype/ }], | ||
| 167 | + }, | ||
| 168 | + { | ||
| 169 | + code: 'async function myFn(){ async function someOtherFn() { return { __proto__: null } } return {} }', | ||
| 170 | + errors: [{ message: /null-prototype/ }], | ||
| 171 | + }, | ||
| 172 | + { | ||
| 173 | + code: 'async function myFn(){ if (true) { return {} } return { __proto__: null } }', | ||
| 174 | + errors: [{ message: /null-prototype/ }], | ||
| 175 | + }, | ||
| 176 | + { | ||
| 177 | + code: 'const myFn = async function myFn(){ return {} }', | ||
| 178 | + errors: [{ message: /null-prototype/ }], | ||
| 179 | + }, | ||
| 180 | + { | ||
| 181 | + code: 'const myFn = async function (){ return {} }', | ||
| 182 | + errors: [{ message: /null-prototype/ }], | ||
| 183 | + }, | ||
| 184 | + { | ||
| 185 | + code: 'const myFn = async () => { return {} }', | ||
| 186 | + errors: [{ message: /null-prototype/ }], | ||
| 187 | + }, | ||
| 188 | + { | ||
| 189 | + code: 'const myFn = async () => ({})', | ||
| 190 | + errors: [{ message: /null-prototype/ }], | ||
| 191 | + }, | ||
| 153 | 192 | { | |
| 154 | 193 | code: 'RegExpPrototypeTest(/some regex/, "some string")', | |
| 155 | 194 | errors: [{ message: /looks up the "exec" property/ }], | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,7 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const CallExpression = (fnName) => `CallExpression[callee.name=${fnName}]`; | |
| 4 | + const AnyFunction = 'FunctionDeclaration, FunctionExpression, ArrowFunctionExpression'; | ||
| 4 | 5 | ||
| 5 | 6 | function checkProperties(context, node) { | |
| 6 | 7 | if ( | |
@@ -25,6 +26,22 @@ function checkProperties(context, node) { | |||
| 25 | 26 | } | |
| 26 | 27 | } | |
| 27 | 28 | ||
| 29 | + function isNullPrototypeObjectExpression(node) { | ||
| 30 | + if (node.type !== 'ObjectExpression') return; | ||
| 31 | + | ||
| 32 | + for (const { key, value } of node.properties) { | ||
| 33 | + if ( | ||
| 34 | + key != null && value != null && | ||
| 35 | + ((key.type === 'Identifier' && key.name === '__proto__') || | ||
| 36 | + (key.type === 'Literal' && key.value === '__proto__')) && | ||
| 37 | + value.type === 'Literal' && value.value === null | ||
| 38 | + ) { | ||
| 39 | + return true; | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | + return false; | ||
| 43 | + } | ||
| 44 | + | ||
| 28 | 45 | function checkPropertyDescriptor(context, node) { | |
| 29 | 46 | if ( | |
| 30 | 47 | node.type === 'CallExpression' && | |
@@ -46,23 +63,12 @@ function checkPropertyDescriptor(context, node) { | |||
| 46 | 63 | }], | |
| 47 | 64 | }); | |
| 48 | 65 | } | |
| 49 | - if (node.type !== 'ObjectExpression') return; | ||
| 50 | - | ||
| 51 | - for (const { key, value } of node.properties) { | ||
| 52 | - if ( | ||
| 53 | - key != null && value != null && | ||
| 54 | - ((key.type === 'Identifier' && key.name === '__proto__') || | ||
| 55 | - (key.type === 'Literal' && key.value === '__proto__')) && | ||
| 56 | - value.type === 'Literal' && value.value === null | ||
| 57 | - ) { | ||
| 58 | - return true; | ||
| 59 | - } | ||
| 66 | + if (isNullPrototypeObjectExpression(node) === false) { | ||
| 67 | + context.report({ | ||
| 68 | + node, | ||
| 69 | + message: 'Must use null-prototype object for property descriptors', | ||
| 70 | + }); | ||
| 60 | 71 | } | |
| 61 | - | ||
| 62 | - context.report({ | ||
| 63 | - node, | ||
| 64 | - message: 'Must use null-prototype object for property descriptors', | ||
| 65 | - }); | ||
| 66 | 72 | } | |
| 67 | 73 | ||
| 68 | 74 | function createUnsafeStringMethodReport(context, name, lookedUpProperty) { | |
@@ -117,6 +123,24 @@ module.exports = { | |||
| 117 | 123 | [`${CallExpression('ObjectCreate')}[arguments.length=2]`](node) { | |
| 118 | 124 | checkProperties(context, node.arguments[1]); | |
| 119 | 125 | }, | |
| 126 | + | ||
| 127 | + [`:matches(${AnyFunction})[async=true]>BlockStatement ReturnStatement>ObjectExpression, :matches(${AnyFunction})[async=true]>ObjectExpression`](node) { | ||
| 128 | + if (node.parent.type === 'ReturnStatement') { | ||
| 129 | + let { parent } = node; | ||
| 130 | + do { | ||
| 131 | + ({ parent } = parent); | ||
| 132 | + } while (!parent.type.includes('Function')); | ||
| 133 | + | ||
| 134 | + if (!parent.async) return; | ||
| 135 | + } | ||
| 136 | + if (isNullPrototypeObjectExpression(node) === false) { | ||
| 137 | + context.report({ | ||
| 138 | + node, | ||
| 139 | + message: 'Use null-prototype when returning from async function', | ||
| 140 | + }); | ||
| 141 | + } | ||
| 142 | + }, | ||
| 143 | + | ||
| 120 | 144 | [CallExpression('RegExpPrototypeTest')](node) { | |
| 121 | 145 | context.report({ | |
| 122 | 146 | node, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments