diff --git a/index.js b/index.js index 0c2b19de..41e54362 100644 --- a/index.js +++ b/index.js @@ -15,7 +15,8 @@ import { warnings } from "./src/warnings.js"; const kMeriyahDefaultOptions = { next: true, loc: true, - raw: true + raw: true, + jsx: true }; export function runASTAnalysis(str, options = Object.create(null)) { @@ -97,7 +98,10 @@ function parseScriptExtended(strToAnalyze, isEcmaScriptModule) { return body; } catch (error) { - if (error.name === "SyntaxError" && error.description.includes("The import keyword")) { + if (error.name === "SyntaxError" && ( + error.description.includes("The import keyword") || + error.description.includes("The export keyword") + )) { const { body } = meriyah.parseScript(strToAnalyze, { ...kMeriyahDefaultOptions, module: true }); diff --git a/package-lock.json b/package-lock.json index 02a82532..c51ef457 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "6.0.0", "license": "MIT", "dependencies": { - "@nodesecure/estree-ast-utils": "^1.3.0", + "@nodesecure/estree-ast-utils": "^1.3.1", "@nodesecure/sec-literal": "^1.2.0", "estree-walker": "^3.0.1", "is-minified-code": "^2.0.0", @@ -572,9 +572,9 @@ } }, "node_modules/@nodesecure/estree-ast-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@nodesecure/estree-ast-utils/-/estree-ast-utils-1.3.0.tgz", - "integrity": "sha512-o7J+OM8+XHm61WdvF/K8mynPRS3SWUgNmynQm0MVnS3Pbz7yGbj+cKDvpg5EZ2zDpZhVDa5Y0u1+MS77eQl8BA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@nodesecure/estree-ast-utils/-/estree-ast-utils-1.3.1.tgz", + "integrity": "sha512-UiCBBrLiD6Q7Yb2OyVt4Ohse17+2gGgI1dnTnrrMi6EAcnJmodkRA6iFT8QLB+LmSfxo7NUSPPFvhGYnJ0sVRw==", "dependencies": { "@nodesecure/sec-literal": "^1.1.0" } @@ -5261,9 +5261,9 @@ } }, "@nodesecure/estree-ast-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@nodesecure/estree-ast-utils/-/estree-ast-utils-1.3.0.tgz", - "integrity": "sha512-o7J+OM8+XHm61WdvF/K8mynPRS3SWUgNmynQm0MVnS3Pbz7yGbj+cKDvpg5EZ2zDpZhVDa5Y0u1+MS77eQl8BA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@nodesecure/estree-ast-utils/-/estree-ast-utils-1.3.1.tgz", + "integrity": "sha512-UiCBBrLiD6Q7Yb2OyVt4Ohse17+2gGgI1dnTnrrMi6EAcnJmodkRA6iFT8QLB+LmSfxo7NUSPPFvhGYnJ0sVRw==", "requires": { "@nodesecure/sec-literal": "^1.1.0" } diff --git a/package.json b/package.json index 2c8afe7d..f8b30ec6 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "homepage": "https://github.com/NodeSecure/js-x-ray#readme", "dependencies": { - "@nodesecure/estree-ast-utils": "^1.3.0", + "@nodesecure/estree-ast-utils": "^1.3.1", "@nodesecure/sec-literal": "^1.2.0", "estree-walker": "^3.0.1", "is-minified-code": "^2.0.0", diff --git a/src/obfuscators/index.js b/src/obfuscators/index.js index 0ae0d7f5..b9f16b69 100644 --- a/src/obfuscators/index.js +++ b/src/obfuscators/index.js @@ -25,8 +25,12 @@ export function isObfuscatedCode(analysis) { } else { // TODO: also implement Dictionnary checkup + const identifiers = analysis.identifiersName + .map((value) => value?.name ?? null) + .filter((name) => typeof name === "string"); + const { prefix, oneTimeOccurence } = Patterns.commonHexadecimalPrefix( - analysis.identifiersName.map((value) => value.name) + identifiers ); const uPrefixNames = new Set(Object.keys(prefix)); diff --git a/test/fixtures/regress/jsx.js b/test/fixtures/regress/jsx.js new file mode 100644 index 00000000..fb70f23c --- /dev/null +++ b/test/fixtures/regress/jsx.js @@ -0,0 +1,8 @@ +const Dropzone = forwardRef(({ children, ...params }, ref) => { + const { open, ...props } = useDropzone(params); + + useImperativeHandle(ref, () => ({ open }), [open]); + + // TODO: Figure out why react-styleguidist cannot create docs if we don't return a jsx element + return {children({ ...props, open })}; +}); diff --git a/test/module.spec.js b/test/module.spec.js index da15c83b..aefc44c4 100644 --- a/test/module.spec.js +++ b/test/module.spec.js @@ -4,7 +4,7 @@ import test from "tape"; // Import Internal Dependencies import { runASTAnalysis } from "../index.js"; -test("it should not crash even if module 'false' is provided", (tape) => { +test("it should not crash even if module 'false' is provided (import keyword)", (tape) => { runASTAnalysis("import * as foo from \"foo\";", { module: false }); @@ -12,6 +12,14 @@ test("it should not crash even if module 'false' is provided", (tape) => { tape.end(); }); +test("it should not crash even if module 'false' is provided (export keyword)", (tape) => { + runASTAnalysis("export const foo = 5;", { + module: false + }); + + tape.end(); +}); + test("it should be capable to extract dependencies name for ECMAScript Modules (ESM)", (tape) => { const { dependencies, warnings } = runASTAnalysis(` import * as http from "http"; diff --git a/test/obfuscated.spec.js b/test/obfuscated.spec.js index 3efae06f..c2dd5cf5 100644 --- a/test/obfuscated.spec.js +++ b/test/obfuscated.spec.js @@ -46,7 +46,6 @@ test("should detect 'freejsobfuscator' obfuscation", (tape) => { const trycatch = readFileSync(new URL("freejsobfuscator.js", FIXTURE_URL), "utf-8"); const { warnings } = runASTAnalysis(trycatch); - tape.strictEqual(warnings.length, 3); tape.deepEqual(getWarningKind(warnings), [ "encoded-literal", "encoded-literal", "obfuscated-code" ].sort()); diff --git a/test/regress.spec.js b/test/regress.spec.js index 5f6a1eac..92a104dd 100644 --- a/test/regress.spec.js +++ b/test/regress.spec.js @@ -14,5 +14,13 @@ const FIXTURE_URL = new URL("fixtures/regress/", import.meta.url); test("it should not crash for prop-types", (tape) => { const propTypes = readFileSync(new URL("prop-types.min.js", FIXTURE_URL), "utf-8"); runASTAnalysis(propTypes); + + tape.end(); +}); + +test("it should not crash for JSX", (tape) => { + const propTypes = readFileSync(new URL("jsx.js", FIXTURE_URL), "utf-8"); + runASTAnalysis(propTypes); + tape.end(); });