@nodesecure/js-x-ray 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,24 @@
1
1
  <p align="center">
2
- <h1 align="center">JS-X-RAY</h1>
2
+ <img src="https://user-images.githubusercontent.com/4438263/213887379-c873eb89-8786-4b5c-8a59-dcca49e01cb8.jpg" alt="@nodesecure/js-x-ray">
3
3
  </p>
4
4
 
5
- ![version](https://img.shields.io/badge/dynamic/json.svg?style=for-the-badge&url=https://raw.githubusercontent.com/NodeSecure/js-x-ray/master/package.json&query=$.version&label=Version)
6
- [![mit](https://img.shields.io/github/license/Naereen/StrapDown.js.svg?style=for-the-badge)](https://github.com/NodeSecure/js-x-ray/blob/master/LICENSE)
7
- [![OpenSSF
8
- Scorecard](https://api.securityscorecards.dev/projects/github.com/NodeSecure/js-x-ray/badge?style=for-the-badge)](https://api.securityscorecards.dev/projects/github.com/NodeSecure/js-x-ray)
9
- ![build](https://img.shields.io/github/actions/workflow/status/NodeSecure/js-x-ray/node.js.yml?style=for-the-badge)
10
- ![coverage](https://img.shields.io/codecov/c/github/NodeSecure/js-x-ray?style=for-the-badge)
5
+ <p align="center">
6
+ <a href="https://github.com/NodeSecure/js-x-ray">
7
+ <img src="https://img.shields.io/badge/dynamic/json.svg?style=for-the-badge&url=https://raw.githubusercontent.com/NodeSecure/js-x-ray/master/package.json&query=$.version&label=Version" alt="npm version">
8
+ </a>
9
+ <a href="https://github.com/NodeSecure/js-x-ray/blob/master/LICENSE">
10
+ <img src="https://img.shields.io/github/license/Naereen/StrapDown.js.svg?style=for-the-badge" alt="license">
11
+ </a>
12
+ <a href="https://api.securityscorecards.dev/projects/github.com/NodeSecure/js-x-ray">
13
+ <img src="https://api.securityscorecards.dev/projects/github.com/NodeSecure/js-x-ray/badge?style=for-the-badge" alt="ossf scorecard">
14
+ </a>
15
+ <a href="https://github.com/NodeSecure/js-x-ray/actions?query=workflow%3A%22Node.js+CI%22">
16
+ <img src="https://img.shields.io/github/actions/workflow/status/NodeSecure/js-x-ray/node.js.yml?style=for-the-badge" alt="github ci workflow">
17
+ </a>
18
+ <a href="https://codecov.io/github/NodeSecure/js-xray">
19
+ <img src="https://img.shields.io/codecov/c/github/NodeSecure/js-x-ray?style=for-the-badge" alt="codecov">
20
+ </a>
21
+ </p>
11
22
 
12
23
  JavaScript AST analysis. This package has been created to export the [Node-Secure](https://github.com/ES-Community/nsecure) AST Analysis to enable better code evolution and allow better access to developers and researchers.
13
24
 
@@ -90,7 +101,8 @@ type WarningName = "parsing-error"
90
101
  | "suspicious-file"
91
102
  | "obfuscated-code"
92
103
  | "weak-crypto"
93
- | "unsafe-import";
104
+ | "unsafe-import"
105
+ | "shady-link";
94
106
 
95
107
  declare const warnings: Record<WarningName, {
96
108
  i18n: string;
@@ -126,6 +138,7 @@ This section describe all the possible warnings returned by JSXRay. Click on the
126
138
  | [suspicious-file](./docs/suspicious-file.md) | ✔️ | A suspicious file with more than ten encoded-literal in it |
127
139
  | [obfuscated-code](./docs/obfuscated-code.md) | ✔️ | There's a very high probability that the code is obfuscated. |
128
140
  | [weak-crypto](./docs/weak-crypto.md) | ✔️ | The code probably contains a weak crypto algorithm (md5, sha1...) |
141
+ | [shady-link](./docs/shady-link.md) | ✔️ | The code contains shady/unsafe link |
129
142
 
130
143
  ## API
131
144
 
@@ -134,8 +147,9 @@ This section describe all the possible warnings returned by JSXRay. Click on the
134
147
 
135
148
  ```ts
136
149
  interface RuntimeOptions {
137
- module?: boolean;
138
- isMinified?: boolean;
150
+ module?: boolean;
151
+ isMinified?: boolean;
152
+ removeHTMLComments?: boolean;
139
153
  }
140
154
  ```
141
155
 
@@ -143,11 +157,11 @@ The method take a first argument which is the code you want to analyse. It will
143
157
 
144
158
  ```ts
145
159
  interface Report {
146
- dependencies: ASTDeps;
147
- warnings: Warning[];
148
- idsLengthAvg: number;
149
- stringScore: number;
150
- isOneLineRequire: boolean;
160
+ dependencies: ASTDeps;
161
+ warnings: Warning[];
162
+ idsLengthAvg: number;
163
+ stringScore: number;
164
+ isOneLineRequire: boolean;
151
165
  }
152
166
  ```
153
167
 
@@ -158,8 +172,9 @@ interface Report {
158
172
 
159
173
  ```ts
160
174
  interface RuntimeOptions {
161
- module?: boolean;
162
- isMinified?: boolean;
175
+ module?: boolean;
176
+ isMinified?: boolean;
177
+ removeHTMLComments?: boolean;
163
178
  }
164
179
  ```
165
180
 
@@ -194,18 +209,18 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
194
209
  <table>
195
210
  <tbody>
196
211
  <tr>
197
- <td align="center"><a href="https://www.linkedin.com/in/thomas-gentilhomme/"><img src="https://avatars.githubusercontent.com/u/4438263?v=4?s=100" width="100px;" alt="Gentilhomme"/><br /><sub><b>Gentilhomme</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/pulls?q=is%3Apr+reviewed-by%3Afraxken" title="Reviewed Pull Requests">👀</a> <a href="#security-fraxken" title="Security">🛡️</a> <a href="https://github.com/NodeSecure/js-x-ray/issues?q=author%3Afraxken" title="Bug reports">🐛</a></td>
198
- <td align="center"><a href="https://github.com/Rossb0b"><img src="https://avatars.githubusercontent.com/u/39910164?v=4?s=100" width="100px;" alt="Nicolas Hallaert"/><br /><sub><b>Nicolas Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Rossb0b" title="Documentation">📖</a></td>
199
- <td align="center"><a href="https://github.com/antoine-coulon"><img src="https://avatars.githubusercontent.com/u/43391199?v=4?s=100" width="100px;" alt="Antoine"/><br /><sub><b>Antoine</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=antoine-coulon" title="Code">💻</a></td>
200
- <td align="center"><a href="https://github.com/Mathieuka"><img src="https://avatars.githubusercontent.com/u/34446722?v=4?s=100" width="100px;" alt="Mathieu"/><br /><sub><b>Mathieu</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Mathieuka" title="Code">💻</a></td>
201
- <td align="center"><a href="https://github.com/Kawacrepe"><img src="https://avatars.githubusercontent.com/u/40260517?v=4?s=100" width="100px;" alt="Vincent Dhennin"/><br /><sub><b>Vincent Dhennin</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Tests">⚠️</a></td>
202
- <td align="center"><a href="http://tonygo.dev"><img src="https://avatars.githubusercontent.com/u/22824417?v=4?s=100" width="100px;" alt="Tony Gorez"/><br /><sub><b>Tony Gorez</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Tests">⚠️</a></td>
203
- <td align="center"><a href="https://github.com/PierreDemailly"><img src="https://avatars.githubusercontent.com/u/39910767?v=4?s=100" width="100px;" alt="PierreD"/><br /><sub><b>PierreD</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=PierreDemailly" title="Tests">⚠️</a></td>
212
+ <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/thomas-gentilhomme/"><img src="https://avatars.githubusercontent.com/u/4438263?v=4?s=100" width="100px;" alt="Gentilhomme"/><br /><sub><b>Gentilhomme</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/pulls?q=is%3Apr+reviewed-by%3Afraxken" title="Reviewed Pull Requests">👀</a> <a href="#security-fraxken" title="Security">🛡️</a> <a href="https://github.com/NodeSecure/js-x-ray/issues?q=author%3Afraxken" title="Bug reports">🐛</a></td>
213
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Rossb0b"><img src="https://avatars.githubusercontent.com/u/39910164?v=4?s=100" width="100px;" alt="Nicolas Hallaert"/><br /><sub><b>Nicolas Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Rossb0b" title="Documentation">📖</a></td>
214
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/antoine-coulon"><img src="https://avatars.githubusercontent.com/u/43391199?v=4?s=100" width="100px;" alt="Antoine"/><br /><sub><b>Antoine</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=antoine-coulon" title="Code">💻</a></td>
215
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Mathieuka"><img src="https://avatars.githubusercontent.com/u/34446722?v=4?s=100" width="100px;" alt="Mathieu"/><br /><sub><b>Mathieu</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Mathieuka" title="Code">💻</a></td>
216
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Kawacrepe"><img src="https://avatars.githubusercontent.com/u/40260517?v=4?s=100" width="100px;" alt="Vincent Dhennin"/><br /><sub><b>Vincent Dhennin</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Tests">⚠️</a></td>
217
+ <td align="center" valign="top" width="14.28%"><a href="http://tonygo.dev"><img src="https://avatars.githubusercontent.com/u/22824417?v=4?s=100" width="100px;" alt="Tony Gorez"/><br /><sub><b>Tony Gorez</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Tests">⚠️</a></td>
218
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/PierreDemailly"><img src="https://avatars.githubusercontent.com/u/39910767?v=4?s=100" width="100px;" alt="PierreD"/><br /><sub><b>PierreD</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=PierreDemailly" title="Tests">⚠️</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=PierreDemailly" title="Code">💻</a></td>
204
219
  </tr>
205
220
  <tr>
206
- <td align="center"><a href="https://www.linkedin.com/in/franck-hallaert/"><img src="https://avatars.githubusercontent.com/u/110826655?v=4?s=100" width="100px;" alt="Franck Hallaert"/><br /><sub><b>Franck Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Aekk0" title="Code">💻</a></td>
207
- <td align="center"><a href="https://maji.kiwi"><img src="https://avatars.githubusercontent.com/u/33150916?v=4?s=100" width="100px;" alt="Maji"/><br /><sub><b>Maji</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=M4gie" title="Code">💻</a></td>
208
- <td align="center"><a href="https://github.com/targos"><img src="https://avatars.githubusercontent.com/u/2352663?v=4?s=100" width="100px;" alt="Michaël Zasso"/><br /><sub><b>Michaël Zasso</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=targos" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/issues?q=author%3Atargos" title="Bug reports">🐛</a></td>
221
+ <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/franck-hallaert/"><img src="https://avatars.githubusercontent.com/u/110826655?v=4?s=100" width="100px;" alt="Franck Hallaert"/><br /><sub><b>Franck Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Aekk0" title="Code">💻</a></td>
222
+ <td align="center" valign="top" width="14.28%"><a href="https://maji.kiwi"><img src="https://avatars.githubusercontent.com/u/33150916?v=4?s=100" width="100px;" alt="Maji"/><br /><sub><b>Maji</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=M4gie" title="Code">💻</a></td>
223
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/targos"><img src="https://avatars.githubusercontent.com/u/2352663?v=4?s=100" width="100px;" alt="Michaël Zasso"/><br /><sub><b>Michaël Zasso</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=targos" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/issues?q=author%3Atargos" title="Bug reports">🐛</a></td>
209
224
  </tr>
210
225
  </tbody>
211
226
  </table>
package/index.js CHANGED
@@ -10,22 +10,30 @@ import isMinified from "is-minified-code";
10
10
  // Import Internal Dependencies
11
11
  import Analysis from "./src/Analysis.js";
12
12
  import { warnings } from "./src/warnings.js";
13
+ import * as utils from "./src/utils.js";
13
14
 
14
15
  // CONSTANTS
15
16
  const kMeriyahDefaultOptions = {
16
17
  next: true,
17
18
  loc: true,
18
- raw: true
19
+ raw: true,
20
+ jsx: true
19
21
  };
20
22
 
21
23
  export function runASTAnalysis(str, options = Object.create(null)) {
22
- const { module = true, isMinified = false } = options;
24
+ const {
25
+ module = true,
26
+ isMinified = false,
27
+ removeHTMLComments = false
28
+ } = options;
23
29
 
24
30
  // Note: if the file start with a shebang then we remove it because 'parseScript' may fail to parse it.
25
31
  // Example: #!/usr/bin/env node
26
32
  const strToAnalyze = str.charAt(0) === "#" ? str.slice(str.indexOf("\n")) : str;
27
- const isEcmaScriptModule = Boolean(module);
28
- const body = parseScriptExtended(strToAnalyze, isEcmaScriptModule);
33
+ const body = parseScriptExtended(strToAnalyze, {
34
+ isEcmaScriptModule: Boolean(module),
35
+ removeHTMLComments
36
+ });
29
37
 
30
38
  const sastAnalysis = new Analysis();
31
39
  sastAnalysis.analyzeSourceString(str);
@@ -56,14 +64,20 @@ export function runASTAnalysis(str, options = Object.create(null)) {
56
64
 
57
65
  export async function runASTAnalysisOnFile(pathToFile, options = {}) {
58
66
  try {
59
- const { packageName = null, module = true } = options;
67
+ const {
68
+ packageName = null,
69
+ module = true,
70
+ removeHTMLComments = false
71
+ } = options;
72
+
60
73
  const str = await fs.readFile(pathToFile, "utf-8");
61
74
  const filePathString = pathToFile instanceof URL ? pathToFile.href : pathToFile;
62
75
 
63
76
  const isMin = filePathString.includes(".min") || isMinified(str);
64
77
  const data = runASTAnalysis(str, {
65
78
  isMinified: isMin,
66
- module: path.extname(filePathString) === ".mjs" ? true : module
79
+ module: path.extname(filePathString) === ".mjs" ? true : module,
80
+ removeHTMLComments
67
81
  });
68
82
  if (packageName !== null) {
69
83
  data.dependencies.removeByName(packageName);
@@ -86,21 +100,39 @@ export async function runASTAnalysisOnFile(pathToFile, options = {}) {
86
100
  }
87
101
  }
88
102
 
89
- function parseScriptExtended(strToAnalyze, isEcmaScriptModule) {
103
+ function parseScriptExtended(strToAnalyze, options = {}) {
104
+ const { isEcmaScriptModule, removeHTMLComments } = options;
105
+
106
+ /**
107
+ * @see https://github.com/NodeSecure/js-x-ray/issues/109
108
+ */
109
+ const cleanedStrToAnalyze = removeHTMLComments ?
110
+ utils.removeHTMLComment(strToAnalyze) : strToAnalyze;
111
+
90
112
  try {
91
- const { body } = meriyah.parseScript(strToAnalyze, {
92
- ...kMeriyahDefaultOptions,
93
- module: isEcmaScriptModule,
94
- globalReturn: !isEcmaScriptModule
95
- });
113
+ const { body } = meriyah.parseScript(
114
+ cleanedStrToAnalyze,
115
+ {
116
+ ...kMeriyahDefaultOptions,
117
+ module: isEcmaScriptModule,
118
+ globalReturn: !isEcmaScriptModule
119
+ }
120
+ );
96
121
 
97
122
  return body;
98
123
  }
99
124
  catch (error) {
100
- if (error.name === "SyntaxError" && error.description.includes("The import keyword")) {
101
- const { body } = meriyah.parseScript(strToAnalyze, {
102
- ...kMeriyahDefaultOptions, module: true
103
- });
125
+ if (error.name === "SyntaxError" && (
126
+ error.description.includes("The import keyword") ||
127
+ error.description.includes("The export keyword")
128
+ )) {
129
+ const { body } = meriyah.parseScript(
130
+ cleanedStrToAnalyze,
131
+ {
132
+ ...kMeriyahDefaultOptions,
133
+ module: true
134
+ }
135
+ );
104
136
 
105
137
  return body;
106
138
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodesecure/js-x-ray",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "JavaScript AST XRay analysis",
5
5
  "type": "module",
6
6
  "exports": "./index.js",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "homepage": "https://github.com/NodeSecure/js-x-ray#readme",
41
41
  "dependencies": {
42
- "@nodesecure/estree-ast-utils": "^1.3.0",
42
+ "@nodesecure/estree-ast-utils": "^1.3.1",
43
43
  "@nodesecure/sec-literal": "^1.2.0",
44
44
  "estree-walker": "^3.0.1",
45
45
  "is-minified-code": "^2.0.0",
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@nodesecure/eslint-config": "^1.6.0",
51
- "@slimio/is": "^1.5.1",
51
+ "@slimio/is": "^2.0.0",
52
52
  "@small-tech/esm-tape-runner": "^2.0.0",
53
53
  "@small-tech/tap-monkey": "^1.4.0",
54
54
  "@types/node": "^18.11.18",
@@ -1,9 +1,9 @@
1
- // Import Third-party Dependencies
2
- import { Utils } from "@nodesecure/sec-literal";
3
-
4
- export function verify(analysis, prefix) {
5
- const pValue = Object.keys(prefix).pop();
6
- const regexStr = `^${Utils.escapeRegExp(pValue)}[a-zA-Z]{1,2}[0-9]{0,2}$`;
7
-
8
- return analysis.identifiersName.every(({ name }) => new RegExp(regexStr).test(name));
9
- }
1
+ // Import Third-party Dependencies
2
+ import { Utils } from "@nodesecure/sec-literal";
3
+
4
+ export function verify(analysis, prefix) {
5
+ const pValue = Object.keys(prefix).pop();
6
+ const regexStr = `^${Utils.escapeRegExp(pValue)}[a-zA-Z]{1,2}[0-9]{0,2}$`;
7
+
8
+ return analysis.identifiersName.every(({ name }) => new RegExp(regexStr).test(name));
9
+ }
@@ -25,8 +25,12 @@ export function isObfuscatedCode(analysis) {
25
25
  }
26
26
  else {
27
27
  // TODO: also implement Dictionnary checkup
28
+ const identifiers = analysis.identifiersName
29
+ .map((value) => value?.name ?? null)
30
+ .filter((name) => typeof name === "string");
31
+
28
32
  const { prefix, oneTimeOccurence } = Patterns.commonHexadecimalPrefix(
29
- analysis.identifiersName.map((value) => value.name)
33
+ identifiers
30
34
  );
31
35
  const uPrefixNames = new Set(Object.keys(prefix));
32
36
 
@@ -1,29 +1,29 @@
1
- // Import Third-party Dependencies
2
- import { getVariableDeclarationIdentifiers } from "@nodesecure/estree-ast-utils";
3
-
4
- /**
5
- * @description Search for AssignmentExpression (Not to be confused with AssignmentPattern).
6
- *
7
- * @see https://github.com/estree/estree/blob/master/es5.md#assignmentexpression
8
- * @example
9
- * (foo = 5)
10
- */
11
- function validateNode(node) {
12
- return [
13
- node.type === "AssignmentExpression"
14
- ];
15
- }
16
-
17
- function main(node, options) {
18
- const { analysis } = options;
19
-
20
- analysis.idtypes.assignExpr++;
21
- for (const { name } of getVariableDeclarationIdentifiers(node.left)) {
22
- analysis.identifiersName.push({ name, type: "assignExpr" });
23
- }
24
- }
25
-
26
- export default {
27
- name: "isAssignmentExpression",
28
- validateNode, main, breakOnMatch: false
29
- };
1
+ // Import Third-party Dependencies
2
+ import { getVariableDeclarationIdentifiers } from "@nodesecure/estree-ast-utils";
3
+
4
+ /**
5
+ * @description Search for AssignmentExpression (Not to be confused with AssignmentPattern).
6
+ *
7
+ * @see https://github.com/estree/estree/blob/master/es5.md#assignmentexpression
8
+ * @example
9
+ * (foo = 5)
10
+ */
11
+ function validateNode(node) {
12
+ return [
13
+ node.type === "AssignmentExpression"
14
+ ];
15
+ }
16
+
17
+ function main(node, options) {
18
+ const { analysis } = options;
19
+
20
+ analysis.idtypes.assignExpr++;
21
+ for (const { name } of getVariableDeclarationIdentifiers(node.left)) {
22
+ analysis.identifiersName.push({ name, type: "assignExpr" });
23
+ }
24
+ }
25
+
26
+ export default {
27
+ name: "isAssignmentExpression",
28
+ validateNode, main, breakOnMatch: false
29
+ };
@@ -1,49 +1,61 @@
1
- // Import Node.js Dependencies
2
- import { builtinModules } from "repl";
3
-
4
- // Import Third-party Dependencies
5
- import { Hex } from "@nodesecure/sec-literal";
6
-
7
- // CONSTANTS
8
- const kNodeDeps = new Set(builtinModules);
9
-
10
- /**
11
- * @description Search for Literal AST Node
12
- * @see https://github.com/estree/estree/blob/master/es5.md#literal
13
- * @example
14
- * "foobar"
15
- */
16
- function validateNode(node) {
17
- return [
18
- node.type === "Literal" && typeof node.value === "string"
19
- ];
20
- }
21
-
22
- function main(node, options) {
23
- const { analysis } = options;
24
-
25
- // We are searching for value obfuscated as hex of a minimum length of 4.
26
- if (/^[0-9A-Fa-f]{4,}$/g.test(node.value)) {
27
- const value = Buffer.from(node.value, "hex").toString();
28
- analysis.analyzeString(value);
29
-
30
- // If the value we are retrieving is the name of a Node.js dependency,
31
- // then we add it to the dependencies list and we throw an unsafe-import at the current location.
32
- if (kNodeDeps.has(value)) {
33
- analysis.dependencies.add(value, node.loc);
34
- analysis.addWarning("unsafe-import", null, node.loc);
35
- }
36
- else if (value === "require" || !Hex.isSafe(node.value)) {
37
- analysis.addWarning("encoded-literal", node.value, node.loc);
38
- }
39
- }
40
- // Else we are checking all other string with our suspect method
41
- else {
42
- analysis.analyzeLiteral(node);
43
- }
44
- }
45
-
46
- export default {
47
- name: "isLiteral",
48
- validateNode, main, breakOnMatch: false
49
- };
1
+ // Import Node.js Dependencies
2
+ import { builtinModules } from "repl";
3
+
4
+ // Import Third-party Dependencies
5
+ import { Hex } from "@nodesecure/sec-literal";
6
+
7
+ // CONSTANTS
8
+ const kNodeDeps = new Set(builtinModules);
9
+ const kShadyLinkRegExps = [
10
+ /(http[s]?:\/\/bit\.ly.*)$/,
11
+ /(http[s]?:\/\/.*\.(link|xyz|tk|ml|ga|cf|gq|pw|top|club|mw|bd|ke|am|sbs|date|quest|cd|bid|cd|ws|icu|cam|uno|email|stream))$/
12
+ ];
13
+
14
+ /**
15
+ * @description Search for Literal AST Node
16
+ * @see https://github.com/estree/estree/blob/master/es5.md#literal
17
+ * @example
18
+ * "foobar"
19
+ */
20
+ function validateNode(node) {
21
+ return [
22
+ node.type === "Literal" && typeof node.value === "string"
23
+ ];
24
+ }
25
+
26
+ function main(node, options) {
27
+ const { analysis } = options;
28
+
29
+ // We are searching for value obfuscated as hex of a minimum length of 4.
30
+ if (/^[0-9A-Fa-f]{4,}$/g.test(node.value)) {
31
+ const value = Buffer.from(node.value, "hex").toString();
32
+ analysis.analyzeString(value);
33
+
34
+ // If the value we are retrieving is the name of a Node.js dependency,
35
+ // then we add it to the dependencies list and we throw an unsafe-import at the current location.
36
+ if (kNodeDeps.has(value)) {
37
+ analysis.dependencies.add(value, node.loc);
38
+ analysis.addWarning("unsafe-import", null, node.loc);
39
+ }
40
+ else if (value === "require" || !Hex.isSafe(node.value)) {
41
+ analysis.addWarning("encoded-literal", node.value, node.loc);
42
+ }
43
+ }
44
+ // Else we are checking all other string with our suspect method
45
+ else {
46
+ for (const regex of kShadyLinkRegExps) {
47
+ if (regex.test(node.value)) {
48
+ analysis.addWarning("shady-link", node.value, node.loc);
49
+
50
+ return;
51
+ }
52
+ }
53
+
54
+ analysis.analyzeLiteral(node);
55
+ }
56
+ }
57
+
58
+ export default {
59
+ name: "isLiteral",
60
+ validateNode, main, breakOnMatch: false
61
+ };
package/src/utils.js CHANGED
@@ -42,3 +42,7 @@ export function extractNode(expectedType) {
42
42
  }
43
43
  };
44
44
  }
45
+
46
+ export function removeHTMLComment(str) {
47
+ return str.replace(/<!--[\s\S]*?(?:-->)/g, "");
48
+ }
package/src/warnings.js CHANGED
@@ -45,6 +45,11 @@ export const warnings = Object.freeze({
45
45
  i18n: "sast_warnings.weak_crypto",
46
46
  severity: "Information",
47
47
  experimental: true
48
+ },
49
+ "shady-link": {
50
+ i18n: "sast_warnings.shady_link",
51
+ severity: "Warning",
52
+ experimental: true
48
53
  }
49
54
  });
50
55
 
package/types/api.d.ts CHANGED
@@ -13,8 +13,18 @@ export {
13
13
  }
14
14
 
15
15
  interface RuntimeOptions {
16
+ /**
17
+ * @default true
18
+ */
16
19
  module?: boolean;
20
+ /**
21
+ * @default false
22
+ */
17
23
  isMinified?: boolean;
24
+ /**
25
+ * @default false
26
+ */
27
+ removeHTMLComments?: boolean;
18
28
  }
19
29
 
20
30
  interface Report {
@@ -27,7 +37,14 @@ interface Report {
27
37
 
28
38
  interface RuntimeFileOptions {
29
39
  packageName?: string;
40
+ /**
41
+ * @default true
42
+ */
30
43
  module?: boolean;
44
+ /**
45
+ * @default false
46
+ */
47
+ removeHTMLComments?: boolean;
31
48
  }
32
49
 
33
50
  type ReportOnFile = {
@@ -15,7 +15,8 @@ type WarningNameWithValue = "parsing-error"
15
15
  | "suspicious-literal"
16
16
  | "suspicious-file"
17
17
  | "obfuscated-code"
18
- | "weak-crypto";
18
+ | "weak-crypto"
19
+ | "shady-link";
19
20
  type WarningName = WarningNameWithValue | "unsafe-import";
20
21
 
21
22
  type WarningLocation = [[number, number], [number, number]];