Skip to content

Commit

Permalink
test: add experimental UT around probes (NodeSecure#29)
Browse files Browse the repository at this point in the history
* wip

* is unsafe callee

* assert eval

* update

* chore: example test

* fix review comments

* chore: use symbol.for

* tests: add tests cases
  • Loading branch information
Kawacrepe authored May 30, 2022
1 parent 55a1661 commit 753c4ec
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 1 deletion.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
test/fixtures
cases/
temp.js
test/probes/fixtures/**/*.js
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,4 @@ dist

temp.js
temp/
.vscode/
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"scripts": {
"lint": "eslint src test",
"prepublishOnly": "pkg-ok",
"test": "cross-env esm-tape-runner 'test/*.spec.js' | tap-monkey",
"test": "cross-env esm-tape-runner 'test/**/*.spec.js' | tap-monkey",
"check": "cross-env npm run lint && npm run test"
},
"repository": {
Expand Down
1 change: 1 addition & 0 deletions test/probes/fixtures/unsafeCallee/1-unsafeCallee.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eval("this");
1 change: 1 addition & 0 deletions test/probes/fixtures/unsafeCallee/2-unsafeCallee.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Function("return this")()
1 change: 1 addition & 0 deletions test/probes/fixtures/unsafeCallee/3-unsafeCallee.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Function('foo');
52 changes: 52 additions & 0 deletions test/probes/isUnsafeCallee.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Require Internal Dependencies
import { parseScript, getSastAnalysis, getWarningOnAnalysisResult } from "../utils/index.js";
import { warnings } from "../../index.js";
import isUnsafeCallee from "../../src/probes/isUnsafeCallee.js";

// Require Third-party dependencies
import test from "tape";

// Require Node.js Dependencies
import { dirname, join } from "path";
import { fileURLToPath } from "url";
import { readFileSync } from "fs";

const __dirname = dirname(fileURLToPath(import.meta.url));
const FIXTURE_PATH = join(__dirname, "fixtures/unsafeCallee");

const warningUnsafeStmt = warnings.unsafeStmt.code;

test("should detect eval", (tape) => {
const str = readFileSync(join(FIXTURE_PATH, "1-unsafeCallee.js"), "utf-8");

const ast = parseScript(str);
const analysis = getSastAnalysis(str, ast.body, isUnsafeCallee);

const result = getWarningOnAnalysisResult(analysis, warningUnsafeStmt);
tape.equal(result.kind, warningUnsafeStmt);
tape.equal(result.value, "eval");
tape.end();
});

test("should detect Function", (tape) => {
const str = readFileSync(join(FIXTURE_PATH, "2-unsafeCallee.js"), "utf-8");

const ast = parseScript(str);
const analysis = getSastAnalysis(str, ast.body, isUnsafeCallee);

const result = getWarningOnAnalysisResult(analysis, warningUnsafeStmt);
tape.equal(result.kind, warningUnsafeStmt);
tape.equal(result.value, "Function");
tape.end();
});

test("should not detect Function", (tape) => {
const str = readFileSync(join(FIXTURE_PATH, "3-unsafeCallee.js"), "utf-8");

const ast = parseScript(str);
const analysis = getSastAnalysis(str, ast.body, isUnsafeCallee);

const result = getWarningOnAnalysisResult(analysis, warningUnsafeStmt);
tape.equal(result, undefined);
tape.end();
});
55 changes: 55 additions & 0 deletions test/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,58 @@
import * as meriyah from "meriyah";
import Analysis from "../../src/Analysis.js";
import { walk } from "estree-walker";

export function getWarningKind(warnings) {
return warnings.slice().map((warn) => warn.kind).sort();
}

export function parseScript(str) {
return meriyah.parseScript(str, {
next: true,
loc: true,
raw: true,
module: true,
globalReturn: false
});
}

function runOnProbes(node, analysis, probe) {
const [isMatching, data = null] = probe.validateNode(node, analysis);

if (isMatching) {
const result = probe.main(node, { analysis, data });

if (result === Symbol.for("skipWalk")) {
return "skip";
}
}

return null;
}

export function getSastAnalysis(strSource, body, probe) {
const sastAnalysis = new Analysis();
sastAnalysis.analyzeSourceString(strSource);

walk(body, {
enter(node) {
// Skip the root of the AST.
if (Array.isArray(node)) {
return;
}


const action = runOnProbes(node, sastAnalysis, probe);

if (action === "skip") {
this.skip();
}
}
});

return sastAnalysis;
}

export function getWarningOnAnalysisResult(analysis, warning) {
return analysis.warnings.find((item) => item.kind === warning);
}

0 comments on commit 753c4ec

Please sign in to comment.