diff --git a/src/ProbeRunner.js b/src/ProbeRunner.js index 08926db..df29e61 100644 --- a/src/ProbeRunner.js +++ b/src/ProbeRunner.js @@ -104,7 +104,7 @@ export class ProbeRunner { if (isMatching) { return probe.main(node, { - analysis: this.sourceFile, + sourceFile: this.sourceFile, data }); } @@ -144,7 +144,7 @@ export class ProbeRunner { } finally { if (probe.teardown) { - probe.teardown({ analysis: this.sourceFile }); + probe.teardown({ sourceFile: this.sourceFile }); } } } diff --git a/src/obfuscators/freejsobfuscator.js b/src/obfuscators/freejsobfuscator.js index 62b847e..97d87d7 100644 --- a/src/obfuscators/freejsobfuscator.js +++ b/src/obfuscators/freejsobfuscator.js @@ -1,9 +1,9 @@ // Import Third-party Dependencies import { Utils } from "@nodesecure/sec-literal"; -export function verify(analysis, prefix) { +export function verify(sourceFile, prefix) { const pValue = Object.keys(prefix).pop(); const regexStr = `^${Utils.escapeRegExp(pValue)}[a-zA-Z]{1,2}[0-9]{0,2}$`; - return analysis.identifiersName.every(({ name }) => new RegExp(regexStr).test(name)); + return sourceFile.identifiersName.every(({ name }) => new RegExp(regexStr).test(name)); } diff --git a/src/obfuscators/index.js b/src/obfuscators/index.js index 74d97e3..d31dda4 100644 --- a/src/obfuscators/index.js +++ b/src/obfuscators/index.js @@ -11,21 +11,21 @@ import * as trojan from "./trojan-source.js"; // CONSTANTS const kMinimumIdsCount = 5; -export function isObfuscatedCode(analysis) { +export function isObfuscatedCode(sourceFile) { let encoderName = null; - if (jsfuck.verify(analysis)) { + if (jsfuck.verify(sourceFile)) { encoderName = "jsfuck"; } - else if (jjencode.verify(analysis)) { + else if (jjencode.verify(sourceFile)) { encoderName = "jjencode"; } - else if (analysis.morseLiterals.size >= 36) { + else if (sourceFile.morseLiterals.size >= 36) { encoderName = "morse"; } else { // TODO: also implement Dictionnary checkup - const identifiers = analysis.identifiersName + const identifiers = sourceFile.identifiersName .map((value) => value?.name ?? null) .filter((name) => typeof name === "string"); @@ -34,18 +34,18 @@ export function isObfuscatedCode(analysis) { ); const uPrefixNames = new Set(Object.keys(prefix)); - if (analysis.counter.identifiers > kMinimumIdsCount && uPrefixNames.size > 0) { - analysis.hasPrefixedIdentifiers = calcAvgPrefixedIdentifiers(analysis, prefix) > 80; + if (sourceFile.counter.identifiers > kMinimumIdsCount && uPrefixNames.size > 0) { + sourceFile.hasPrefixedIdentifiers = calcAvgPrefixedIdentifiers(sourceFile, prefix) > 80; } - if (uPrefixNames.size === 1 && freejsobfuscator.verify(analysis, prefix)) { + if (uPrefixNames.size === 1 && freejsobfuscator.verify(sourceFile, prefix)) { encoderName = "freejsobfuscator"; } - else if (obfuscatorio.verify(analysis)) { + else if (obfuscatorio.verify(sourceFile)) { encoderName = "obfuscator.io"; } - // else if ((analysis.counter.identifiers > (kMinimumIdsCount * 3) && analysis.hasPrefixedIdentifiers) - // && (oneTimeOccurence <= 3 || analysis.counter.encodedArrayValue > 0)) { + // else if ((sourceFile.counter.identifiers > (kMinimumIdsCount * 3) && sourceFile.hasPrefixedIdentifiers) + // && (oneTimeOccurence <= 3 || sourceFile.counter.encodedArrayValue > 0)) { // encoderName = "unknown"; // } } @@ -57,13 +57,13 @@ export function hasTrojanSource(sourceString) { return trojan.verify(sourceString); } -function calcAvgPrefixedIdentifiers(analysis, prefix) { +function calcAvgPrefixedIdentifiers(sourceFile, prefix) { const valuesArr = Object.values(prefix).slice().sort((left, right) => left - right); if (valuesArr.length === 0) { return 0; } const nbOfPrefixedIds = valuesArr.length === 1 ? valuesArr.pop() : (valuesArr.pop() + valuesArr.pop()); - const maxIds = analysis.counter.identifiers - analysis.idtypes.property; + const maxIds = sourceFile.counter.identifiers - sourceFile.idtypes.property; return ((nbOfPrefixedIds / maxIds) * 100); } diff --git a/src/obfuscators/jjencode.js b/src/obfuscators/jjencode.js index 740c48b..d366c41 100644 --- a/src/obfuscators/jjencode.js +++ b/src/obfuscators/jjencode.js @@ -4,15 +4,15 @@ import { notNullOrUndefined } from "../utils/index.js"; // CONSTANTS const kJJRegularSymbols = new Set(["$", "_"]); -export function verify(analysis) { - if (analysis.counter.variableDeclarator > 0 || analysis.counter.functionDeclaration > 0) { +export function verify(sourceFile) { + if (sourceFile.counter.variableDeclarator > 0 || sourceFile.counter.functionDeclaration > 0) { return false; } - if (analysis.idtypes.assignExpr > analysis.idtypes.property) { + if (sourceFile.idtypes.assignExpr > sourceFile.idtypes.property) { return false; } - const matchCount = analysis.identifiersName.filter(({ name }) => { + const matchCount = sourceFile.identifiersName.filter(({ name }) => { if (!notNullOrUndefined(name)) { return false; } @@ -20,7 +20,7 @@ export function verify(analysis) { return charsCode.every((char) => kJJRegularSymbols.has(char)); }).length; - const pourcent = ((matchCount / analysis.identifiersName.length) * 100); + const pourcent = ((matchCount / sourceFile.identifiersName.length) * 100); return pourcent > 80; } diff --git a/src/obfuscators/jsfuck.js b/src/obfuscators/jsfuck.js index 8f4ca53..c7aadac 100644 --- a/src/obfuscators/jsfuck.js +++ b/src/obfuscators/jsfuck.js @@ -1,11 +1,11 @@ // CONSTANTS const kJSFuckMinimumDoubleUnaryExpr = 5; -export function verify(analysis) { - const hasZeroAssign = analysis.idtypes.assignExpr === 0 - && analysis.idtypes.functionDeclaration === 0 - && analysis.idtypes.property === 0 - && analysis.idtypes.variableDeclarator === 0; +export function verify(sourceFile) { + const hasZeroAssign = sourceFile.idtypes.assignExpr === 0 + && sourceFile.idtypes.functionDeclaration === 0 + && sourceFile.idtypes.property === 0 + && sourceFile.idtypes.variableDeclarator === 0; - return hasZeroAssign && analysis.counter.doubleUnaryArray >= kJSFuckMinimumDoubleUnaryExpr; + return hasZeroAssign && sourceFile.counter.doubleUnaryArray >= kJSFuckMinimumDoubleUnaryExpr; } diff --git a/src/obfuscators/obfuscator-io.js b/src/obfuscators/obfuscator-io.js index 826b054..c93931d 100644 --- a/src/obfuscators/obfuscator-io.js +++ b/src/obfuscators/obfuscator-io.js @@ -1,13 +1,13 @@ -export function verify(analysis) { - if (analysis.counter.memberExpr > 0) { +export function verify(sourceFile) { + if (sourceFile.counter.memberExpr > 0) { return false; } - const hasSomePatterns = analysis.counter.doubleUnaryArray > 0 - || analysis.counter.deepBinaryExpr > 0 - || analysis.counter.encodedArrayValue > 0 - || analysis.hasDictionaryString; + const hasSomePatterns = sourceFile.counter.doubleUnaryArray > 0 + || sourceFile.counter.deepBinaryExpr > 0 + || sourceFile.counter.encodedArrayValue > 0 + || sourceFile.hasDictionaryString; // TODO: hasPrefixedIdentifiers only work for hexadecimal id names generator - return analysis.hasPrefixedIdentifiers && hasSomePatterns; + return sourceFile.hasPrefixedIdentifiers && hasSomePatterns; } diff --git a/src/probes/isArrayExpression.js b/src/probes/isArrayExpression.js index c96cb94..ff62485 100644 --- a/src/probes/isArrayExpression.js +++ b/src/probes/isArrayExpression.js @@ -17,9 +17,9 @@ function validateNode(node) { ]; } -function main(node, { analysis }) { +function main(node, { sourceFile }) { kLiteralExtractor( - (literalNode) => analysis.analyzeLiteral(literalNode, true), + (literalNode) => sourceFile.analyzeLiteral(literalNode, true), node.elements ); } diff --git a/src/probes/isAssignmentExpression.js b/src/probes/isAssignmentExpression.js index 1c4af2c..636cd42 100644 --- a/src/probes/isAssignmentExpression.js +++ b/src/probes/isAssignmentExpression.js @@ -15,11 +15,11 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; - analysis.idtypes.assignExpr++; + sourceFile.idtypes.assignExpr++; for (const { name } of getVariableDeclarationIdentifiers(node.left)) { - analysis.identifiersName.push({ name, type: "assignExpr" }); + sourceFile.identifiersName.push({ name, type: "assignExpr" }); } } diff --git a/src/probes/isBinaryExpression.js b/src/probes/isBinaryExpression.js index d5a2f33..feec158 100644 --- a/src/probes/isBinaryExpression.js +++ b/src/probes/isBinaryExpression.js @@ -12,11 +12,11 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; const [binaryExprDeepness, hasUnaryExpression] = walkBinaryExpression(node); if (binaryExprDeepness >= 3 && hasUnaryExpression) { - analysis.counter.deepBinaryExpr++; + sourceFile.counter.deepBinaryExpr++; } } diff --git a/src/probes/isClassDeclaration.js b/src/probes/isClassDeclaration.js index 44e2a30..4d6f6b4 100644 --- a/src/probes/isClassDeclaration.js +++ b/src/probes/isClassDeclaration.js @@ -11,10 +11,10 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; kIdExtractor( - ({ name }) => analysis.identifiersName.push({ name, type: "class" }), + ({ name }) => sourceFile.identifiersName.push({ name, type: "class" }), [node.id, node.superClass] ); } diff --git a/src/probes/isFunction.js b/src/probes/isFunction.js index d9eb7d7..2b4733c 100644 --- a/src/probes/isFunction.js +++ b/src/probes/isFunction.js @@ -18,18 +18,18 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; kIdExtractor( - ({ name }) => analysis.identifiersName.push({ name, type: "params" }), + ({ name }) => sourceFile.identifiersName.push({ name, type: "params" }), node.params ); if (node.id === null || node.id.type !== "Identifier") { return; } - analysis.idtypes.functionDeclaration++; - analysis.identifiersName.push({ name: node.id.name, type: "functionDeclaration" }); + sourceFile.idtypes.functionDeclaration++; + sourceFile.identifiersName.push({ name: node.id.name, type: "functionDeclaration" }); } export default { diff --git a/src/probes/isImportDeclaration.js b/src/probes/isImportDeclaration.js index 102d30d..de381f2 100644 --- a/src/probes/isImportDeclaration.js +++ b/src/probes/isImportDeclaration.js @@ -14,14 +14,14 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; // Searching for dangerous import "data:text/javascript;..." statement. // see: https://2ality.com/2019/10/eval-via-import.html if (node.source.value.startsWith("data:text/javascript")) { - analysis.addWarning("unsafe-import", node.source.value, node.loc); + sourceFile.addWarning("unsafe-import", node.source.value, node.loc); } - analysis.addDependency(node.source.value, node.loc); + sourceFile.addDependency(node.source.value, node.loc); } export default { diff --git a/src/probes/isLiteral.js b/src/probes/isLiteral.js index 6b0751d..176a84a 100644 --- a/src/probes/isLiteral.js +++ b/src/probes/isLiteral.js @@ -24,34 +24,34 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; // We are searching for value obfuscated as hex of a minimum length of 4. if (/^[0-9A-Fa-f]{4,}$/g.test(node.value)) { const value = Buffer.from(node.value, "hex").toString(); - analysis.analyzeString(value); + sourceFile.analyzeString(value); // If the value we are retrieving is the name of a Node.js dependency, // then we add it to the dependencies list and we throw an unsafe-import at the current location. if (kNodeDeps.has(value)) { - analysis.addDependency(value, node.loc); - analysis.addWarning("unsafe-import", null, node.loc); + sourceFile.addDependency(value, node.loc); + sourceFile.addWarning("unsafe-import", null, node.loc); } else if (value === "require" || !Hex.isSafe(node.value)) { - analysis.addWarning("encoded-literal", node.value, node.loc); + sourceFile.addWarning("encoded-literal", node.value, node.loc); } } // Else we are checking all other string with our suspect method else { for (const regex of kShadyLinkRegExps) { if (regex.test(node.value)) { - analysis.addWarning("shady-link", node.value, node.loc); + sourceFile.addWarning("shady-link", node.value, node.loc); return; } } - analysis.analyzeLiteral(node); + sourceFile.analyzeLiteral(node); } } diff --git a/src/probes/isLiteralRegex.js b/src/probes/isLiteralRegex.js index 461db18..4c498a5 100644 --- a/src/probes/isLiteralRegex.js +++ b/src/probes/isLiteralRegex.js @@ -15,11 +15,11 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; // We use the safe-regex package to detect whether or not regex is safe! if (!safeRegex(node.regex.pattern)) { - analysis.addWarning("unsafe-regex", node.regex.pattern, node.loc); + sourceFile.addWarning("unsafe-regex", node.regex.pattern, node.loc); } } diff --git a/src/probes/isMemberExpression.js b/src/probes/isMemberExpression.js index 973737b..4257e2b 100644 --- a/src/probes/isMemberExpression.js +++ b/src/probes/isMemberExpression.js @@ -5,9 +5,9 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; - analysis.counter[node.computed ? "computedMemberExpr" : "memberExpr"]++; + sourceFile.counter[node.computed ? "computedMemberExpr" : "memberExpr"]++; } export default { diff --git a/src/probes/isMethodDefinition.js b/src/probes/isMethodDefinition.js index 284342c..13f3304 100644 --- a/src/probes/isMethodDefinition.js +++ b/src/probes/isMethodDefinition.js @@ -11,10 +11,10 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; kIdExtractor( - ({ name }) => analysis.identifiersName.push({ name, type: "method" }), + ({ name }) => sourceFile.identifiersName.push({ name, type: "method" }), [node.key] ); } diff --git a/src/probes/isObjectExpression.js b/src/probes/isObjectExpression.js index 6809150..ab110af 100644 --- a/src/probes/isObjectExpression.js +++ b/src/probes/isObjectExpression.js @@ -11,15 +11,15 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; for (const property of node.properties) { if (property.type !== "Property" || property.key.type !== "Identifier") { continue; } - analysis.idtypes.property++; - analysis.identifiersName.push({ name: property.key.name, type: "property" }); + sourceFile.idtypes.property++; + sourceFile.identifiersName.push({ name: property.key.name, type: "property" }); } } diff --git a/src/probes/isRegexObject.js b/src/probes/isRegexObject.js index 5091340..50cbaa6 100644 --- a/src/probes/isRegexObject.js +++ b/src/probes/isRegexObject.js @@ -15,7 +15,7 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; const arg = node.arguments[0]; /** @@ -29,7 +29,7 @@ function main(node, options) { // We use the safe-regex package to detect whether or not regex is safe! if (!safeRegex(pattern)) { - analysis.addWarning("unsafe-regex", pattern, node.loc); + sourceFile.addWarning("unsafe-regex", pattern, node.loc); } } diff --git a/src/probes/isRequire.js b/src/probes/isRequire.js index d1966ab..325b141 100644 --- a/src/probes/isRequire.js +++ b/src/probes/isRequire.js @@ -49,14 +49,14 @@ function validateNodeEvalRequire(node) { ]; } -function teardown({ analysis }) { - analysis.dependencyAutoWarning = false; +function teardown({ sourceFile }) { + sourceFile.dependencyAutoWarning = false; } function main(node, options) { - const { analysis, data: calleeName } = options; - const { tracer } = analysis; + const { sourceFile, data: calleeName } = options; + const { tracer } = sourceFile; if (node.arguments.length === 0) { return; @@ -64,26 +64,26 @@ function main(node, options) { const arg = node.arguments.at(0); if (calleeName === "eval") { - analysis.dependencyAutoWarning = true; + sourceFile.dependencyAutoWarning = true; } switch (arg.type) { // const foo = "http"; require(foo); case "Identifier": - if (analysis.tracer.literalIdentifiers.has(arg.name)) { - analysis.addDependency( - analysis.tracer.literalIdentifiers.get(arg.name), + if (sourceFile.tracer.literalIdentifiers.has(arg.name)) { + sourceFile.addDependency( + sourceFile.tracer.literalIdentifiers.get(arg.name), node.loc ); } else { - analysis.addWarning("unsafe-import", null, node.loc); + sourceFile.addWarning("unsafe-import", null, node.loc); } break; // require("http") case "Literal": - analysis.addDependency(arg.value, node.loc); + sourceFile.addDependency(arg.value, node.loc); break; // require(["ht", "tp"]) @@ -93,10 +93,10 @@ function main(node, options) { .trim(); if (value === "") { - analysis.addWarning("unsafe-import", null, node.loc); + sourceFile.addWarning("unsafe-import", null, node.loc); } else { - analysis.addDependency(value, node.loc); + sourceFile.addDependency(value, node.loc); } break; } @@ -104,7 +104,7 @@ function main(node, options) { // require("ht" + "tp"); case "BinaryExpression": { if (arg.operator !== "+") { - analysis.addWarning("unsafe-import", null, node.loc); + sourceFile.addWarning("unsafe-import", null, node.loc); break; } @@ -113,10 +113,10 @@ function main(node, options) { tracer, stopOnUnsupportedNode: true }); - analysis.addDependency([...iter].join(""), node.loc); + sourceFile.addDependency([...iter].join(""), node.loc); } catch { - analysis.addWarning("unsafe-import", null, node.loc); + sourceFile.addWarning("unsafe-import", null, node.loc); } break; } @@ -124,10 +124,10 @@ function main(node, options) { // require(Buffer.from("...", "hex").toString()); case "CallExpression": { const { dependencies, triggerWarning } = walkRequireCallExpression(arg, tracer); - dependencies.forEach((depName) => analysis.addDependency(depName, node.loc, true)); + dependencies.forEach((depName) => sourceFile.addDependency(depName, node.loc, true)); if (triggerWarning) { - analysis.addWarning("unsafe-import", null, node.loc); + sourceFile.addWarning("unsafe-import", null, node.loc); } // We skip walking the tree to avoid anymore warnings... @@ -135,7 +135,7 @@ function main(node, options) { } default: - analysis.addWarning("unsafe-import", null, node.loc); + sourceFile.addWarning("unsafe-import", null, node.loc); } } diff --git a/src/probes/isUnaryExpression.js b/src/probes/isUnaryExpression.js index 1d2586f..e6654dc 100644 --- a/src/probes/isUnaryExpression.js +++ b/src/probes/isUnaryExpression.js @@ -11,12 +11,12 @@ function validateNode(node) { } function main(node, options) { - const { analysis } = options; + const { sourceFile } = options; // Example: !![] // See: https://docs.google.com/document/d/11ZrfW0bDQ-kd7Gr_Ixqyk8p3TGvxckmhFH3Z8dFoPhY/edit# if (node.argument.type === "UnaryExpression" && node.argument.argument.type === "ArrayExpression") { - analysis.counter.doubleUnaryArray++; + sourceFile.counter.doubleUnaryArray++; } } diff --git a/src/probes/isUnsafeCallee.js b/src/probes/isUnsafeCallee.js index 2c75989..72947d1 100644 --- a/src/probes/isUnsafeCallee.js +++ b/src/probes/isUnsafeCallee.js @@ -13,7 +13,7 @@ function validateNode(node) { } function main(node, options) { - const { analysis, data: calleeName } = options; + const { sourceFile, data: calleeName } = options; if ( calleeName === "Function" && @@ -22,7 +22,7 @@ function main(node, options) { ) { return ProbeSignals.Skip; } - analysis.addWarning("unsafe-stmt", calleeName, node.loc); + sourceFile.addWarning("unsafe-stmt", calleeName, node.loc); return ProbeSignals.Skip; } diff --git a/src/probes/isVariableDeclaration.js b/src/probes/isVariableDeclaration.js index 5182f47..3732d29 100644 --- a/src/probes/isVariableDeclaration.js +++ b/src/probes/isVariableDeclaration.js @@ -12,14 +12,14 @@ function validateNode(node) { } function main(mainNode, options) { - const { analysis } = options; + const { sourceFile } = options; - analysis.varkinds[mainNode.kind]++; + sourceFile.varkinds[mainNode.kind]++; for (const node of mainNode.declarations) { - analysis.idtypes.variableDeclarator++; + sourceFile.idtypes.variableDeclarator++; for (const { name } of getVariableDeclarationIdentifiers(node.id)) { - analysis.identifiersName.push({ name, type: "variableDeclarator" }); + sourceFile.identifiersName.push({ name, type: "variableDeclarator" }); } } } diff --git a/src/probes/isWeakCrypto.js b/src/probes/isWeakCrypto.js index 98325a7..8738439 100644 --- a/src/probes/isWeakCrypto.js +++ b/src/probes/isWeakCrypto.js @@ -21,11 +21,11 @@ function validateNode(node, { tracer }) { return [data !== null && data.identifierOrMemberExpr === "crypto.createHash"]; } -function main(node, { analysis }) { +function main(node, { sourceFile }) { const arg = node.arguments.at(0); if (kWeakAlgorithms.has(arg.value)) { - analysis.addWarning("weak-crypto", arg.value, node.loc); + sourceFile.addWarning("weak-crypto", arg.value, node.loc); } } diff --git a/test/ProbeRunner.spec.js b/test/ProbeRunner.spec.js index 143671a..c3c0aa4 100644 --- a/test/ProbeRunner.spec.js +++ b/test/ProbeRunner.spec.js @@ -89,12 +89,12 @@ describe("ProbeRunner", () => { assert.strictEqual(fakeProbe.main.mock.calls.length, 1); assert.deepEqual(fakeProbe.main.mock.calls.at(0).arguments, [ - astNode, { analysis: sourceFile, data: null } + astNode, { sourceFile, data: null } ]); assert.strictEqual(fakeProbe.teardown.mock.calls.length, 1); assert.deepEqual(fakeProbe.teardown.mock.calls.at(0).arguments, [ - { analysis: sourceFile } + { sourceFile } ]); }); diff --git a/test/probes/isArrayExpression.spec.js b/test/probes/isArrayExpression.spec.js index 7a66d0f..318ea76 100644 --- a/test/probes/isArrayExpression.spec.js +++ b/test/probes/isArrayExpression.spec.js @@ -12,12 +12,12 @@ test("it should trigger analyzeLiteral method one time", (t) => { const ast = parseScript(str); const sastAnalysis = getSastAnalysis(str, isArrayExpression); - t.mock.method(sastAnalysis.analysis, "analyzeLiteral"); + t.mock.method(sastAnalysis.sourceFile, "analyzeLiteral"); sastAnalysis.execute(ast.body); assert.strictEqual(sastAnalysis.warnings().length, 0); - const calls = sastAnalysis.analysis.analyzeLiteral.mock.calls; + const calls = sastAnalysis.sourceFile.analyzeLiteral.mock.calls; assert.strictEqual(calls.length, 1); const literalNode = calls[0].arguments[0]; @@ -30,10 +30,10 @@ test("it should trigger analyzeLiteral method two times (ignoring the holey betw const ast = parseScript(str); const sastAnalysis = getSastAnalysis(str, isArrayExpression); - t.mock.method(sastAnalysis.analysis, "analyzeLiteral"); + t.mock.method(sastAnalysis.sourceFile, "analyzeLiteral"); sastAnalysis.execute(ast.body); - const calls = sastAnalysis.analysis.analyzeLiteral.mock.calls; + const calls = sastAnalysis.sourceFile.analyzeLiteral.mock.calls; assert.strictEqual(calls.length, 2); assert.strictEqual(calls[0].arguments[0].value, 5); assert.strictEqual(calls[1].arguments[0].value, 10); @@ -45,10 +45,10 @@ test("it should trigger analyzeLiteral one time (ignoring non-literal Node)", (t const ast = parseScript(str); const sastAnalysis = getSastAnalysis(str, isArrayExpression); - t.mock.method(sastAnalysis.analysis, "analyzeLiteral"); + t.mock.method(sastAnalysis.sourceFile, "analyzeLiteral"); sastAnalysis.execute(ast.body); - const calls = sastAnalysis.analysis.analyzeLiteral.mock.calls; + const calls = sastAnalysis.sourceFile.analyzeLiteral.mock.calls; assert.strictEqual(calls.length, 1); const literalNode = calls[0].arguments[0]; diff --git a/test/probes/isAssignmentExpression.spec.js b/test/probes/isAssignmentExpression.spec.js index b76e8ec..3376ae3 100644 --- a/test/probes/isAssignmentExpression.spec.js +++ b/test/probes/isAssignmentExpression.spec.js @@ -9,17 +9,17 @@ import isAssignmentExpression from "../../src/probes/isAssignmentExpression.js"; test("should detect 1 assignment expression", () => { const str = "obj = { foo: 1 }"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isAssignmentExpression) + const { sourceFile } = getSastAnalysis(str, isAssignmentExpression) .execute(ast.body); - assert.equal(analysis.idtypes.assignExpr, 1); + assert.equal(sourceFile.idtypes.assignExpr, 1); }); test("should detect 0 assignment expression", () => { const str = "Object.assign(obj, { foo: 1 })"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isAssignmentExpression) + const { sourceFile } = getSastAnalysis(str, isAssignmentExpression) .execute(ast.body); - assert.equal(analysis.idtypes.assignExpr, 0); + assert.equal(sourceFile.idtypes.assignExpr, 0); }); diff --git a/test/probes/isBinaryExpression.spec.js b/test/probes/isBinaryExpression.spec.js index 6858fd8..c1fe51a 100644 --- a/test/probes/isBinaryExpression.spec.js +++ b/test/probes/isBinaryExpression.spec.js @@ -9,17 +9,17 @@ import isBinaryExpression from "../../src/probes/isBinaryExpression.js"; test("should detect 1 deep binary expression", () => { const str = "0x1*-0x12df+-0x1fb9*-0x1+0x2*-0x66d"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isBinaryExpression) + const { sourceFile } = getSastAnalysis(str, isBinaryExpression) .execute(ast.body); - assert.equal(analysis.counter.deepBinaryExpr, 1); + assert.equal(sourceFile.counter.deepBinaryExpr, 1); }); test("should not detect deep binary expression", () => { const str = "10 + 5 - (10)"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isBinaryExpression) + const { sourceFile } = getSastAnalysis(str, isBinaryExpression) .execute(ast.body); - assert.equal(analysis.counter.deepBinaryExpr, 0); + assert.equal(sourceFile.counter.deepBinaryExpr, 0); }); diff --git a/test/probes/isClassDeclaration.spec.js b/test/probes/isClassDeclaration.spec.js index dbafd07..715d20f 100644 --- a/test/probes/isClassDeclaration.spec.js +++ b/test/probes/isClassDeclaration.spec.js @@ -9,10 +9,10 @@ import isClassDeclaration from "../../src/probes/isClassDeclaration.js"; test("should detect two identifiers (class name and superClass name A.K.A extends)", () => { const str = "class File extends Blob {}"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isClassDeclaration) + const { sourceFile } = getSastAnalysis(str, isClassDeclaration) .execute(ast.body); - assert.deepEqual(analysis.identifiersName, [ + assert.deepEqual(sourceFile.identifiersName, [ { name: "File", type: "class" }, { name: "Blob", type: "class" } ]); @@ -21,10 +21,10 @@ test("should detect two identifiers (class name and superClass name A.K.A extend test("should detect one identifier because there is no superClass (extension)", () => { const str = "class File {}"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isClassDeclaration) + const { sourceFile } = getSastAnalysis(str, isClassDeclaration) .execute(ast.body); - assert.deepEqual(analysis.identifiersName, [ + assert.deepEqual(sourceFile.identifiersName, [ { name: "File", type: "class" } ]); }); @@ -32,10 +32,10 @@ test("should detect one identifier because there is no superClass (extension)", test("should detect one identifier because superClass is not an Identifier but a CallExpression", () => { const str = "class File extends (foo()) {}"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isClassDeclaration) + const { sourceFile } = getSastAnalysis(str, isClassDeclaration) .execute(ast.body); - assert.deepEqual(analysis.identifiersName, [ + assert.deepEqual(sourceFile.identifiersName, [ { name: "File", type: "class" } ]); }); diff --git a/test/probes/isFunction.spec.js b/test/probes/isFunction.spec.js index 6afa25f..4611173 100644 --- a/test/probes/isFunction.spec.js +++ b/test/probes/isFunction.spec.js @@ -9,37 +9,37 @@ import isFunctionDeclaration from "../../src/probes/isFunction.js"; test("should detect one FunctionDeclaration node", () => { const str = "function foo() {}"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isFunctionDeclaration) + const { sourceFile } = getSastAnalysis(str, isFunctionDeclaration) .execute(ast.body); - assert.equal(analysis.idtypes.functionDeclaration, 1); + assert.equal(sourceFile.idtypes.functionDeclaration, 1); }); test("should detect zero FunctionDeclaration (because foo is a CallExpression Node)", () => { const str = "foo()"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isFunctionDeclaration) + const { sourceFile } = getSastAnalysis(str, isFunctionDeclaration) .execute(ast.body); - assert.equal(analysis.idtypes.functionDeclaration, 0); + assert.equal(sourceFile.idtypes.functionDeclaration, 0); }); test("should detect zero FunctionDeclaration for an IIFE (because there is no Identifier)", () => { const str = "(function() {})()"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isFunctionDeclaration) + const { sourceFile } = getSastAnalysis(str, isFunctionDeclaration) .execute(ast.body); - assert.equal(analysis.idtypes.functionDeclaration, 0); + assert.equal(sourceFile.idtypes.functionDeclaration, 0); }); test("should detect three identifiers (one function declaration and two params identifier)", () => { const str = "function foo(err, result) {}"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isFunctionDeclaration) + const { sourceFile } = getSastAnalysis(str, isFunctionDeclaration) .execute(ast.body); - assert.deepEqual(analysis.identifiersName, [ + assert.deepEqual(sourceFile.identifiersName, [ { name: "err", type: "params" }, { name: "result", type: "params" }, { name: "foo", type: "functionDeclaration" } diff --git a/test/probes/isImportDeclaration.spec.js b/test/probes/isImportDeclaration.spec.js index b7e88ba..e2bcf75 100644 --- a/test/probes/isImportDeclaration.spec.js +++ b/test/probes/isImportDeclaration.spec.js @@ -9,40 +9,40 @@ import isImportDeclaration from "../../src/probes/isImportDeclaration.js"; test("should detect 1 dependency for an ImportNamespaceSpecifier", () => { const str = "import * as foo from \"bar\""; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isImportDeclaration) + const { sourceFile } = getSastAnalysis(str, isImportDeclaration) .execute(ast.body); - const { dependencies } = analysis; + const { dependencies } = sourceFile; assert.ok(dependencies.has("bar")); }); test("should detect 1 dependency for an ImportDefaultSpecifier", () => { const str = "import foo from \"bar\""; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isImportDeclaration) + const { sourceFile } = getSastAnalysis(str, isImportDeclaration) .execute(ast.body); - const { dependencies } = analysis; + const { dependencies } = sourceFile; assert.ok(dependencies.has("bar")); }); test("should detect 1 dependency for an ImportSpecifier", () => { const str = "import { xd } from \"bar\""; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isImportDeclaration) + const { sourceFile } = getSastAnalysis(str, isImportDeclaration) .execute(ast.body); - const { dependencies } = analysis; + const { dependencies } = sourceFile; assert.ok(dependencies.has("bar")); }); test("should detect 1 dependency with no specificiers", () => { const str = "import \"bar\""; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isImportDeclaration) + const { sourceFile } = getSastAnalysis(str, isImportDeclaration) .execute(ast.body); - const { dependencies } = analysis; + const { dependencies } = sourceFile; assert.ok(dependencies.has("bar")); }); diff --git a/test/probes/isLiteral.spec.js b/test/probes/isLiteral.spec.js index f4faade..9cf2c50 100644 --- a/test/probes/isLiteral.spec.js +++ b/test/probes/isLiteral.spec.js @@ -11,7 +11,7 @@ test("should throw an unsafe-import because the hexadecimal string is equal to t const ast = parseScript(str); const sastAnalysis = getSastAnalysis(str, isLiteral); - t.mock.method(sastAnalysis.analysis, "analyzeString"); + t.mock.method(sastAnalysis.sourceFile, "analyzeString"); sastAnalysis.execute(ast.body); assert.strictEqual(sastAnalysis.warnings().length, 1); @@ -19,7 +19,7 @@ test("should throw an unsafe-import because the hexadecimal string is equal to t assert.strictEqual(warning.kind, "unsafe-import"); assert.ok(sastAnalysis.dependencies().has("http")); - const calls = sastAnalysis.analysis.analyzeString.mock.calls; + const calls = sastAnalysis.sourceFile.analyzeString.mock.calls; assert.strictEqual(calls.length, 1); assert.ok(calls[0].arguments.includes("http")); }); @@ -30,14 +30,14 @@ test("should throw an encoded-literal warning because the hexadecimal value is e const ast = parseScript(str); const sastAnalysis = getSastAnalysis(str, isLiteral); - t.mock.method(sastAnalysis.analysis, "analyzeString"); + t.mock.method(sastAnalysis.sourceFile, "analyzeString"); sastAnalysis.execute(ast.body); assert.strictEqual(sastAnalysis.warnings().length, 1); const warning = sastAnalysis.getWarning("encoded-literal"); assert.strictEqual(warning.value, "72657175697265"); - const calls = sastAnalysis.analysis.analyzeString.mock.calls; + const calls = sastAnalysis.sourceFile.analyzeString.mock.calls; assert.strictEqual(calls.length, 1); assert.ok(calls[0].arguments.includes("require")); }); @@ -68,11 +68,11 @@ test("should not throw any warnings without hexadecimal value (and should call a const ast = parseScript(str); const sastAnalysis = getSastAnalysis(str, isLiteral); - t.mock.method(sastAnalysis.analysis, "analyzeLiteral"); + t.mock.method(sastAnalysis.sourceFile, "analyzeLiteral"); sastAnalysis.execute(ast.body); assert.strictEqual(sastAnalysis.warnings().length, 0); - const calls = sastAnalysis.analysis.analyzeLiteral.mock.calls; + const calls = sastAnalysis.sourceFile.analyzeLiteral.mock.calls; assert.strictEqual(calls.length, 1); const astNode = calls[0].arguments[0]; diff --git a/test/probes/isMemberExpression.spec.js b/test/probes/isMemberExpression.spec.js index 56a2191..b5dbfad 100644 --- a/test/probes/isMemberExpression.spec.js +++ b/test/probes/isMemberExpression.spec.js @@ -9,36 +9,36 @@ import isMemberExpression from "../../src/probes/isMemberExpression.js"; test("should detect 1 member expression", () => { const str = "process.mainModule"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isMemberExpression) + const { sourceFile } = getSastAnalysis(str, isMemberExpression) .execute(ast.body); - assert.equal(analysis.counter.memberExpr, 1); + assert.equal(sourceFile.counter.memberExpr, 1); }); test("should detect 2 members expressions", () => { const str = "process.mainModule.foo"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isMemberExpression) + const { sourceFile } = getSastAnalysis(str, isMemberExpression) .execute(ast.body); - assert.equal(analysis.counter.memberExpr, 2); + assert.equal(sourceFile.counter.memberExpr, 2); }); test("should detect 1 member expression and 2 nodes", () => { const str = "process.mainModule['foo']['bar']"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isMemberExpression) + const { sourceFile } = getSastAnalysis(str, isMemberExpression) .execute(ast.body); - assert.equal(analysis.counter.memberExpr, 1); - assert.equal(analysis.counter.computedMemberExpr, 2); + assert.equal(sourceFile.counter.memberExpr, 1); + assert.equal(sourceFile.counter.computedMemberExpr, 2); }); test("should detect 0 member expression", () => { const str = "process"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isMemberExpression) + const { sourceFile } = getSastAnalysis(str, isMemberExpression) .execute(ast.body); - assert.equal(analysis.counter.memberExpr, 0); + assert.equal(sourceFile.counter.memberExpr, 0); }); diff --git a/test/probes/isMethodDefinition.spec.js b/test/probes/isMethodDefinition.spec.js index 1380dd4..b6fa003 100644 --- a/test/probes/isMethodDefinition.spec.js +++ b/test/probes/isMethodDefinition.spec.js @@ -12,10 +12,10 @@ test("should detect two identifiers (constructor and one method definition)", () foo() {} }`; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isMethodDefinition) + const { sourceFile } = getSastAnalysis(str, isMethodDefinition) .execute(ast.body); - assert.deepEqual(analysis.identifiersName, [ + assert.deepEqual(sourceFile.identifiersName, [ { name: "constructor", type: "method" }, { name: "foo", type: "method" } ]); @@ -27,10 +27,10 @@ test("should detect two identifiers (getter and setter)", () => { set bar(value) {} }`; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isMethodDefinition) + const { sourceFile } = getSastAnalysis(str, isMethodDefinition) .execute(ast.body); - assert.deepEqual(analysis.identifiersName, [ + assert.deepEqual(sourceFile.identifiersName, [ { name: "foo", type: "method" }, { name: "bar", type: "method" } ]); diff --git a/test/probes/isObjectExpression.spec.js b/test/probes/isObjectExpression.spec.js index 34173b7..b6f3991 100644 --- a/test/probes/isObjectExpression.spec.js +++ b/test/probes/isObjectExpression.spec.js @@ -13,20 +13,20 @@ const FIXTURE_URL = new URL("fixtures/objectExpression/", import.meta.url); test("object with 2 properties should have 2 identifiers", () => { const str = readFileSync(new URL("object-objectExpression.js", FIXTURE_URL), "utf-8"); const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isObjectExpression) + const { sourceFile } = getSastAnalysis(str, isObjectExpression) .execute(ast.body); - assert.equal(analysis.idtypes.property, 2); - assert.equal(analysis.identifiersName[0].name, "log"); - assert.equal(analysis.identifiersName[1].name, "latest"); + assert.equal(sourceFile.idtypes.property, 2); + assert.equal(sourceFile.identifiersName[0].name, "log"); + assert.equal(sourceFile.identifiersName[1].name, "latest"); }); test("class with 2 properties should have 0 identifier", () => { const str = readFileSync(new URL("class-objectExpression.js", FIXTURE_URL), "utf-8"); const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isObjectExpression) + const { sourceFile } = getSastAnalysis(str, isObjectExpression) .execute(ast.body); - assert.equal(analysis.idtypes.property, 0); - assert.equal(analysis.identifiersName.length, 0); + assert.equal(sourceFile.idtypes.property, 0); + assert.equal(sourceFile.identifiersName.length, 0); }); diff --git a/test/probes/isUnaryExpression.spec.js b/test/probes/isUnaryExpression.spec.js index ceeee8d..f5aa027 100644 --- a/test/probes/isUnaryExpression.spec.js +++ b/test/probes/isUnaryExpression.spec.js @@ -9,17 +9,17 @@ import isUnaryExpression from "../../src/probes/isUnaryExpression.js"; test("should detect one UnaryArray", () => { const str = "!![]"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isUnaryExpression) + const { sourceFile } = getSastAnalysis(str, isUnaryExpression) .execute(ast.body); - assert.strictEqual(analysis.counter.doubleUnaryArray, 1); + assert.strictEqual(sourceFile.counter.doubleUnaryArray, 1); }); test("should not detect any UnaryArray", () => { const str = "![]"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isUnaryExpression) + const { sourceFile } = getSastAnalysis(str, isUnaryExpression) .execute(ast.body); - assert.strictEqual(analysis.counter.doubleUnaryArray, 0); + assert.strictEqual(sourceFile.counter.doubleUnaryArray, 0); }); diff --git a/test/probes/isVariableDeclaration.spec.js b/test/probes/isVariableDeclaration.spec.js index b34480e..f18ff73 100644 --- a/test/probes/isVariableDeclaration.spec.js +++ b/test/probes/isVariableDeclaration.spec.js @@ -9,10 +9,10 @@ import isVariableDeclaration from "../../src/probes/isVariableDeclaration.js"; test("should detect and save all VariableDeclaration kinds", () => { const str = "var foo; const a = 5; let b = 'foo';"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isVariableDeclaration) + const { sourceFile } = getSastAnalysis(str, isVariableDeclaration) .execute(ast.body); - assert.deepEqual(analysis.varkinds, { + assert.deepEqual(sourceFile.varkinds, { const: 1, let: 1, var: 1 @@ -22,19 +22,19 @@ test("should detect and save all VariableDeclaration kinds", () => { test("should count the number of VariableDeclarator node", () => { const str = "let a,b,c;"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isVariableDeclaration) + const { sourceFile } = getSastAnalysis(str, isVariableDeclaration) .execute(ast.body); - assert.strictEqual(analysis.idtypes.variableDeclarator, 3); + assert.strictEqual(sourceFile.idtypes.variableDeclarator, 3); }); test("should detect and save VariableDeclarator Identifier", () => { const str = "let foobar = 5;"; const ast = parseScript(str); - const { analysis } = getSastAnalysis(str, isVariableDeclaration) + const { sourceFile } = getSastAnalysis(str, isVariableDeclaration) .execute(ast.body); - assert.deepEqual(analysis.identifiersName, [ + assert.deepEqual(sourceFile.identifiersName, [ { name: "foobar", type: "variableDeclarator" diff --git a/test/utils/index.js b/test/utils/index.js index 22450e1..b6a170e 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -25,20 +25,20 @@ export function getSastAnalysis( probe ) { return { - analysis: new SourceFile(sourceCodeString), + sourceFile: new SourceFile(sourceCodeString), getWarning(warning) { - return this.analysis.warnings.find( + return this.sourceFile.warnings.find( (item) => item.kind === warning ); }, warnings() { - return this.analysis.warnings; + return this.sourceFile.warnings; }, dependencies() { - return this.analysis.dependencies; + return this.sourceFile.dependencies; }, execute(body) { - const probeRunner = new ProbeRunner(this.analysis, [probe]); + const probeRunner = new ProbeRunner(this.sourceFile, [probe]); const self = this; walk(body, { @@ -48,7 +48,7 @@ export function getSastAnalysis( return; } - self.analysis.tracer.walk(node); + self.sourceFile.tracer.walk(node); const action = probeRunner.walk(node); if (action === "skip") {