UNPKG

@nodesecure/js-x-ray

Version:
91 lines 3.51 kB
// Import Node.js Dependencies import path from "node:path"; // Import Internal Dependencies import { Hex } from "../../utils/index.js"; import { arrayExpressionToString, getCallExpressionArguments, getMemberExpressionIdentifier } from "../../estree/index.js"; import { isCallExpression, isLiteral } from "../../estree/types.js"; import { walkEnter } from "../../walker/index.js"; export class RequireCallExpressionWalker { tracer; dependencies = new Set(); triggerWarning = true; constructor(tracer) { this.tracer = tracer; } reset() { this.dependencies.clear(); this.triggerWarning = true; } walk(callExprNode) { this.reset(); // we need the `this` context of doWalk.enter const self = this; walkEnter(callExprNode, function enter(node) { if (!isCallExpression(node) || node.arguments.length === 0) { return; } const castedNode = node; const rootArgument = castedNode.arguments.at(0); if (rootArgument.type === "Literal" && typeof rootArgument.value === "string" && Hex.isHex(rootArgument.value)) { self.dependencies.add(Buffer.from(rootArgument.value, "hex").toString()); this.skip(); return; } const fullName = castedNode.callee.type === "MemberExpression" ? [...getMemberExpressionIdentifier(castedNode.callee)].join(".") : castedNode.callee.name; const tracedFullName = self.tracer.getDataFromIdentifier(fullName)?.identifierOrMemberExpr ?? fullName; switch (tracedFullName) { case "atob": self.#handleAtob(castedNode); break; case "Buffer.from": self.#handleBufferFrom(castedNode); break; case "require.resolve": self.#handleRequireResolve(rootArgument); break; case "path.join": case "path.resolve": self.#handlePathJoin(castedNode); break; } }); return { dependencies: this.dependencies, triggerWarning: this.triggerWarning }; } #handleAtob(node) { const nodeArguments = getCallExpressionArguments(node, { externalIdentifierLookup: (name) => this.tracer.literalIdentifiers.get(name)?.value ?? null }); if (nodeArguments !== null && nodeArguments.length > 0) { this.dependencies.add(Buffer.from(nodeArguments.at(0), "base64").toString()); } } #handleBufferFrom(node) { const [element] = node.arguments; if (element.type === "ArrayExpression") { const depName = [...arrayExpressionToString(element)].join("").trim(); this.dependencies.add(depName); } } #handleRequireResolve(node) { if (isLiteral(node)) { this.dependencies.add(node.value); } } #handlePathJoin(node) { if (!node.arguments.every((arg) => isLiteral(arg))) { return; } const constructedPath = path.posix.join(...node.arguments.map((arg) => arg.value)); this.dependencies.add(constructedPath); this.triggerWarning = false; } } //# sourceMappingURL=RequireCallExpressionWalker.js.map