Skip to content

Commit

Permalink
start refacto options param
Browse files Browse the repository at this point in the history
  • Loading branch information
tchapacan committed Mar 11, 2024
1 parent bec2abb commit 901f01b
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 25 deletions.
6 changes: 4 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ function runASTAnalysis(
) {
const {
customParser = new JsSourceParser(),
astOptions = { isReplacing: false, customProbe: [] },
...opts
} = options;

const analyser = new AstAnalyser(customParser);
const analyser = new AstAnalyser(customParser, options.astOptions);

return analyser.analyse(str, opts);
}
Expand All @@ -23,10 +24,11 @@ async function runASTAnalysisOnFile(
) {
const {
customParser = new JsSourceParser(),
astOptions = { isReplacing: false, customProbe: [] },
...opts
} = options;

const analyser = new AstAnalyser(customParser);
const analyser = new AstAnalyser(customParser, options.astOptions);

return analyser.analyseFile(pathToFile, opts);
}
Expand Down
10 changes: 5 additions & 5 deletions src/AstAnalyser.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import { JsSourceParser } from "./JsSourceParser.js";
export class AstAnalyser {
/**
* @constructor
* @param { SourceParser } [parser]
* @param {SourceParser} [parser]
* @param astOptions
*/
constructor(parser = new JsSourceParser(), customProbes = [], mergeMode = "append") {
constructor(parser = new JsSourceParser(), astOptions = { isReplacing: false, customProbe: [] }) {
this.parser = parser;
this.customProbes = customProbes;
this.mergeMode = mergeMode;
this.astOptions = astOptions;
}

analyse(str, options = Object.create(null)) {
Expand All @@ -33,7 +33,7 @@ export class AstAnalyser {
isEcmaScriptModule: Boolean(module)
});

const source = new SourceFile(str, this.customProbes, this.mergeMode);
const source = new SourceFile(str, this.astOptions);

// we walk each AST Nodes, this is a purely synchronous I/O
walk(body, {
Expand Down
13 changes: 5 additions & 8 deletions src/SourceFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,18 @@ export class SourceFile {
encodedLiterals = new Map();
warnings = [];

constructor(sourceCodeString, customProbes = [], mergeMode = "append") {
constructor(sourceCodeString, astOptions = { isReplacing: false, customProbes: [] }) {
this.tracer = new VariableTracer()
.enableDefaultTracing()
.trace("crypto.createHash", {
followConsecutiveAssignment: true, moduleName: "crypto"
});

let mergedProbes;
if (Array.isArray(customProbes) && customProbes.length > 0) {
mergedProbes = mergeMode === "replace" ? customProbes : [...ProbeRunner.Defaults, ...customProbes];
let probes = ProbeRunner.Defaults;
if (Array.isArray(astOptions.customProbes) && astOptions.customProbes.length > 0) {
probes = astOptions.isReplacing === true ? astOptions.customProbes : [...probes, ...astOptions.customProbes];
}
else {
mergedProbes = ProbeRunner.Defaults;
}
this.probesRunner = new ProbeRunner(this, mergedProbes);
this.probesRunner = new ProbeRunner(this, probes);

if (trojan.verify(sourceCodeString)) {
this.addWarning("obfuscated-code", "trojan-source");
Expand Down
8 changes: 7 additions & 1 deletion test/AstAnalyser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ describe("AstAnalyser", (t) => {
const preparedSource = getAnalyser().prepareSource(`
<!--
// == fake comment == //
const yo = 5;
//-->
`, {
Expand Down Expand Up @@ -236,6 +236,12 @@ describe("AstAnalyser", (t) => {
assert.deepEqual([...result.dependencies.keys()], []);
});
});

it("should instantiate with correct default ASTOptions", () => {
const analyser = new AstAnalyser();
assert.strictEqual(analyser.astOptions.isReplacing, false);
assert.deepStrictEqual(analyser.astOptions.customProbe, []);
});
});
});

Expand Down
22 changes: 20 additions & 2 deletions test/issues/221-inject-custom-probes.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import assert from "node:assert";
import { JsSourceParser } from "../../src/JsSourceParser.js";
import { AstAnalyser } from "../../src/AstAnalyser.js";
import { ProbeSignals } from "../../src/ProbeRunner.js";
import { runASTAnalysis } from "../../index.js";

/**
* @see https://github.com/NodeSecure/js-x-ray/issues/221
Expand Down Expand Up @@ -37,7 +38,7 @@ const customProbes = [
];

test("should append to list of probes (default)", () => {
const analyser = new AstAnalyser(new JsSourceParser(), customProbes);
const analyser = new AstAnalyser(new JsSourceParser(), { customProbes });
const result = analyser.analyse(kIncriminedCodeSample);

assert.equal(result.warnings[0].kind, kWarningUnsafeDanger);
Expand All @@ -47,9 +48,26 @@ test("should append to list of probes (default)", () => {
});

test("should replace list of probes", () => {
const analyser = new AstAnalyser(new JsSourceParser(), customProbes, "replace");
const analyser = new AstAnalyser(new JsSourceParser(), { customProbes, isReplacing: true });
const result = analyser.analyse(kIncriminedCodeSample);

assert.equal(result.warnings[0].kind, kWarningUnsafeDanger);
assert.equal(result.warnings.length, 1);
});


test("should append list of probes using runASTAnalysis", () => {
const result = runASTAnalysis(kIncriminedCodeSample, { astOptions: { isReplacing: false, customProbes } });

assert.equal(result.warnings[0].kind, kWarningUnsafeDanger);
assert.equal(result.warnings[1].kind, kWarningUnsafeImport);
assert.equal(result.warnings[2].kind, kWarningUnsafeStmt);
assert.equal(result.warnings.length, 3);
});

test("should replace list of probes using runASTAnalysis", () => {
const result = runASTAnalysis(kIncriminedCodeSample, { astOptions: { isReplacing: true, customProbes } });

assert.equal(result.warnings[0].kind, kWarningUnsafeDanger);
assert.equal(result.warnings.length, 1);
});
3 changes: 1 addition & 2 deletions test/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ export function getSastAnalysis(
return this.sourceFile.dependencies;
},
execute(body) {
const probes = Array.isArray(probe) ? probe : [probe];
const probeRunner = new ProbeRunner(this.sourceFile, probes);
const probeRunner = new ProbeRunner(this.sourceFile, [probe]);
const self = this;

walk(body, {
Expand Down
38 changes: 33 additions & 5 deletions types/api.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Warning } from "./warnings.js";
import { Statement } from "meriyah/dist/src/estree.js";
import {validateFunctionName} from "meriyah/dist/src/common";

export {
AstAnalyser,
Expand Down Expand Up @@ -34,6 +35,17 @@ interface Dependency {
location?: null | SourceLocation;
}

interface RootOptions {
/**
* @default ASTOptions
*/
ASTOptions?: ASTOptions;
/**
* @default RuntimeOptions
*/
RuntimeOptions?: RuntimeOptions;
}

interface RuntimeOptions {
/**
* @default true
Expand All @@ -47,10 +59,26 @@ interface RuntimeOptions {
* @default false
*/
removeHTMLComments?: boolean;

customParser?: SourceParser;
}

interface ASTOptions {
/**
* @default false
*/
isReplacing?: boolean;
/**
* @default []
*/
customParser?: Probe[] | null;
}

interface Probe {
validate: Function[] | Function;
main: Function[] | Function;
}

interface Report {
dependencies: Map<string, Dependency>;
warnings: Warning[];
Expand All @@ -74,14 +102,14 @@ type ReportOnFile = {
}

interface SourceParser {
parse(source: string, options: unknown): Statement[];
parse(source: string, astOptions: ASTOptions): Statement[];
}

declare class AstAnalyser {
constructor(parser?: SourceParser);
constructor(parser?: SourceParser, options?: ASTOptions);
analyse: (str: string, options?: Omit<RuntimeOptions, "customParser">) => Report;
analyzeFile(pathToFile: string, options?: Omit<RuntimeFileOptions, "customParser">): Promise<ReportOnFile>;
}

declare function runASTAnalysis(str: string, options?: RuntimeOptions): Report;
declare function runASTAnalysisOnFile(pathToFile: string, options?: RuntimeFileOptions): Promise<ReportOnFile>;
declare function runASTAnalysis(str: string, options?: RootOptions): Report;
declare function runASTAnalysisOnFile(pathToFile: string, options?: RootOptions): Promise<ReportOnFile>;

0 comments on commit 901f01b

Please sign in to comment.