UNPKG

@nodesecure/js-x-ray

Version:
99 lines 2.58 kB
// Import Internal Dependencies import { getCallExpressionIdentifier, getMemberExpressionIdentifier } from "../estree/index.js"; import { generateWarning } from "../warnings.js"; // CONSTANTS export const JS_TYPES = new Set([ "AggregateError", "Array", "ArrayBuffer", "BigInt", "BigInt64Array", "BigUint64Array", "Boolean", "DataView", "Date", "Error", "EvalError", "FinalizationRegistry", "Float32Array", "Float64Array", "Function", "Int16Array", "Int32Array", "Int8Array", "Map", "Number", "Object", "Promise", "Proxy", "RangeError", "ReferenceError", "Reflect", "RegExp", "Set", "SharedArrayBuffer", "String", "Symbol", "SyntaxError", "TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray", "URIError", "WeakMap", "WeakRef", "WeakSet" ]); /** * @description Search for monkey patching of built-in prototypes. * @example * Array.prototype.map = function() {}; */ function validateNodeAssignment(node, ctx) { if (node.type !== "AssignmentExpression" || node.left.type !== "MemberExpression") { return [false]; } return validateMemberExpression(node.left, ctx); } function validateDefineProperty(node, ctx) { if (node.type !== "CallExpression") { return [false]; } const id = getCallExpressionIdentifier(node); if ((id !== "Object.defineProperty" && id !== "Reflect.defineProperty")) { return [false]; } const firstArg = node.arguments.at(0); if (firstArg?.type !== "MemberExpression") { return [false]; } return validateMemberExpression(firstArg, ctx); } function validateMemberExpression(node, ctx) { const iter = getMemberExpressionIdentifier(node, { externalIdentifierLookup: (name) => ctx.sourceFile.tracer.literalIdentifiers.get(name)?.value ?? null }); const jsTypeName = iter.next().value; if (typeof jsTypeName !== "string" || !JS_TYPES.has(jsTypeName)) { return [false]; } return [ iter.next().value === "prototype", `${jsTypeName}.prototype` ]; } function main(node, options) { const { sourceFile, data: prototypeName } = options; sourceFile.warnings.push(generateWarning("monkey-patch", { value: prototypeName, location: node.loc })); } export default { name: "isMonkeyPatch", validateNode: [ validateNodeAssignment, validateDefineProperty ], main }; //# sourceMappingURL=isMonkeyPatch.js.map